2323import Foundation
2424import UIKit
2525
26-
2726// MARK: - NextGrowingTextView: UIScrollView
2827
2928open class NextGrowingTextView : UIScrollView {
30-
31- // MARK: - Public
32-
29+
30+ // MARK: - Nested types
31+
3332 open class Delegates {
3433 open var willChangeHeight : ( CGFloat ) -> Void = { _ in }
3534 open var didChangeHeight : ( CGFloat ) -> Void = { _ in }
3635 }
3736
37+ // MARK: - Properties
38+
3839 open var delegates = Delegates ( )
3940
4041 open var textView : UITextView {
@@ -47,11 +48,11 @@ open class NextGrowingTextView: UIScrollView {
4748 }
4849 set {
4950 guard newValue > 1 else {
50- minHeight = 1
51+ _minHeight = 1
5152 return
5253 }
5354
54- minHeight = simulateHeight ( newValue)
55+ _minHeight = simulateHeight ( newValue)
5556 _minNumberOfLines = newValue
5657 }
5758 }
@@ -63,20 +64,60 @@ open class NextGrowingTextView: UIScrollView {
6364 set {
6465
6566 guard newValue > 1 else {
66- maxHeight = 1
67+ _maxHeight = 1
6768 return
6869 }
6970
70- maxHeight = simulateHeight ( newValue)
71+ _maxHeight = simulateHeight ( newValue)
7172 _maxNumberOfLines = newValue
7273 }
7374 }
7475
7576 open var disableAutomaticScrollToBottom = false
77+
78+ open var placeholderAttributedText : NSAttributedString ? {
79+ get { return _textView. placeholderAttributedText }
80+ set { _textView. placeholderAttributedText = newValue }
81+ }
82+
83+ open override var inputView : UIView ? {
84+ get {
85+ return _textView. inputView
86+ }
87+ set {
88+ _textView. inputView = newValue
89+ }
90+ }
91+
92+ open override var isFirstResponder : Bool {
93+ return _textView. isFirstResponder
94+ }
95+
96+ open override func becomeFirstResponder( ) -> Bool {
97+ return _textView. becomeFirstResponder ( )
98+ }
99+
100+ open override func resignFirstResponder( ) -> Bool {
101+ return _textView. resignFirstResponder ( )
102+ }
103+
104+ open override var intrinsicContentSize : CGSize {
105+ return measureFrame ( measureTextViewSize ( ) ) . size
106+ }
107+
108+ private let _textView : NextGrowingInternalTextView
109+ private var _maxNumberOfLines : Int = 0
110+ private var _minNumberOfLines : Int = 0
111+ private var _maxHeight : CGFloat = 0
112+ private var _minHeight : CGFloat = 0
113+ private var _previousFrame : CGRect = CGRect . zero
114+
115+ // MARK: - Initializers
76116
77117 public override init ( frame: CGRect ) {
118+
78119 _textView = NextGrowingInternalTextView ( frame: CGRect ( origin: CGPoint . zero, size: frame. size) )
79- previousFrame = frame
120+ _previousFrame = frame
80121
81122 super. init ( frame: frame)
82123
@@ -90,85 +131,53 @@ open class NextGrowingTextView: UIScrollView {
90131 super. init ( coder: aDecoder)
91132
92133 _textView. frame = bounds
93- previousFrame = frame
134+ _previousFrame = frame
94135 setup ( )
95136 }
137+
138+ // MARK: - Functions
96139
97140 open override func layoutSubviews( ) {
98141 super. layoutSubviews ( )
99- if previousFrame . width != bounds. width {
100- previousFrame = frame
142+ if _previousFrame . width != bounds. width {
143+ _previousFrame = frame
101144 fitToScrollView ( )
102145 }
103146 }
104147
105148 // MARK: UIResponder
106-
107- open override var inputView : UIView ? {
108- get {
109- return _textView. inputView
110- }
111- set {
112- _textView. inputView = newValue
113- }
114- }
115-
116- open override var isFirstResponder : Bool {
117- return self . _textView. isFirstResponder
118- }
119-
120- open override func becomeFirstResponder( ) -> Bool {
121- return self . _textView. becomeFirstResponder ( )
122- }
123-
124- open override func resignFirstResponder( ) -> Bool {
125- return self . _textView. resignFirstResponder ( )
126- }
127-
128- open override var intrinsicContentSize : CGSize {
129- return self . measureFrame ( self . measureTextViewSize ( ) ) . size
130- }
131-
149+
132150 open override func reloadInputViews( ) {
133151 super. reloadInputViews ( )
134152 _textView. reloadInputViews ( )
135153 }
136154
137- // MARK: Private
138-
139- fileprivate let _textView : NextGrowingInternalTextView
140-
141- fileprivate var _maxNumberOfLines : Int = 0
142- fileprivate var _minNumberOfLines : Int = 0
143- fileprivate var maxHeight : CGFloat = 0
144- fileprivate var minHeight : CGFloat = 0
145-
146- fileprivate func setup( ) {
155+ private func setup( ) {
147156
148- self . _textView. isScrollEnabled = false
149- self . _textView. font = UIFont . systemFont ( ofSize: 16 )
150- self . _textView. backgroundColor = UIColor . clear
151- self . addSubview ( _textView)
152- self . minHeight = simulateHeight ( 1 )
153- self . maxNumberOfLines = 3
157+ _textView. isScrollEnabled = false
158+ _textView. font = UIFont . systemFont ( ofSize: 16 )
159+ _textView. backgroundColor = UIColor . clear
160+ addSubview ( _textView)
161+ _minHeight = simulateHeight ( 1 )
162+ maxNumberOfLines = 3
154163
155164 _textView. didChange = { [ weak self] in
156165 self ? . fitToScrollView ( )
157166 }
158167 }
159168
160- fileprivate func measureTextViewSize( ) -> CGSize {
169+ private func measureTextViewSize( ) -> CGSize {
161170 return _textView. sizeThatFits ( CGSize ( width: self . bounds. width, height: CGFloat . infinity) )
162171 }
163172
164- fileprivate func measureFrame( _ contentSize: CGSize ) -> CGRect {
173+ private func measureFrame( _ contentSize: CGSize ) -> CGRect {
165174
166175 let selfSize : CGSize
167176
168- if contentSize. height < self . minHeight || !self . _textView. hasText {
169- selfSize = CGSize ( width: contentSize. width, height: self . minHeight )
170- } else if self . maxHeight > 0 && contentSize. height > self . maxHeight {
171- selfSize = CGSize ( width: contentSize. width, height: self . maxHeight )
177+ if contentSize. height < _minHeight || !_textView. hasText {
178+ selfSize = CGSize ( width: contentSize. width, height: _minHeight )
179+ } else if _maxHeight > 0 && contentSize. height > _maxHeight {
180+ selfSize = CGSize ( width: contentSize. width, height: _maxHeight )
172181 } else {
173182 selfSize = contentSize
174183 }
@@ -178,7 +187,7 @@ open class NextGrowingTextView: UIScrollView {
178187 return _frame
179188 }
180189
181- fileprivate func fitToScrollView( ) {
190+ private func fitToScrollView( ) {
182191
183192 let shouldScrollToBottom = contentOffset. y == contentSize. height - frame. height
184193 let actualTextViewSize = measureTextViewSize ( )
@@ -192,7 +201,7 @@ open class NextGrowingTextView: UIScrollView {
192201
193202 let newScrollViewFrame = measureFrame ( actualTextViewSize)
194203
195- if oldScrollViewFrame. height != newScrollViewFrame. height && newScrollViewFrame. height <= maxHeight {
204+ if oldScrollViewFrame. height != newScrollViewFrame. height && newScrollViewFrame. height <= _maxHeight {
196205 flashScrollIndicators ( )
197206 delegates. willChangeHeight ( newScrollViewFrame. height)
198207 }
@@ -207,25 +216,25 @@ open class NextGrowingTextView: UIScrollView {
207216 delegates. didChangeHeight ( frame. height)
208217 }
209218
210- fileprivate func scrollToBottom( ) {
219+ private func scrollToBottom( ) {
211220 if !disableAutomaticScrollToBottom {
212221 let offset = contentOffset
213222 contentOffset = CGPoint ( x: offset. x, y: contentSize. height - frame. height)
214223 }
215224 }
216225
217- fileprivate func updateMinimumAndMaximumHeight( ) {
218- self . minHeight = simulateHeight ( 1 )
219- self . maxHeight = simulateHeight ( self . maxNumberOfLines)
220- self . fitToScrollView ( )
226+ private func updateMinimumAndMaximumHeight( ) {
227+ _minHeight = simulateHeight ( 1 )
228+ _maxHeight = simulateHeight ( maxNumberOfLines)
229+ fitToScrollView ( )
221230 }
222231
223- fileprivate func simulateHeight( _ line: Int ) -> CGFloat {
232+ private func simulateHeight( _ line: Int ) -> CGFloat {
224233
225234 let saveText = _textView. text
226235 var newText = " - "
227236
228- self . _textView. isHidden = true
237+ _textView. isHidden = true
229238
230239 for _ in 0 ..< line- 1 {
231240 newText += " \n |W| "
@@ -235,18 +244,9 @@ open class NextGrowingTextView: UIScrollView {
235244
236245 let height = measureTextViewSize ( ) . height
237246
238- self . _textView. text = saveText
239- self . _textView. isHidden = false
247+ _textView. text = saveText
248+ _textView. isHidden = false
240249
241250 return height
242251 }
243-
244- fileprivate var previousFrame : CGRect = CGRect . zero
245- }
246-
247- extension NextGrowingTextView {
248- public var placeholderAttributedText : NSAttributedString ? {
249- get { return _textView. placeholderAttributedText }
250- set { _textView. placeholderAttributedText = newValue }
251- }
252252}
0 commit comments