I have a TextView
that has a constraint of min height of 33. The scroll is disabled from the storyboard. The TextView
should increase in height based on the content until it reaches the max height of 100. Then I changes the scrollEnabled to true and the height of the TextView
to max height of 100, but the height changes to the 33. How can I fix this problem?
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var messageTextView: UITextView!
let messageTextViewMaxHeight: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
self.messageTextView.delegate = self
}
func textViewDidChange(textView: UITextView) {
if textView.frame.size.height >= self.messageTextViewMaxHeight {
textView.scrollEnabled = true
textView.frame.size.height = self.messageTextViewMaxHeight
} else {
textView.scrollEnabled = false
}
}
}
It seems your code requires two changes, and it will work fine.
Change code as below:
import UIKit
class ViewController: UIViewController, UITextViewDelegate
{
@IBOutlet weak var messageTextView: UITextView!
let messageTextViewMaxHeight: CGFloat = 100
override func viewDidLoad()
{
super.viewDidLoad()
messageTextView.delegate = self
}
func textViewDidChange(textView: UITextView)
{
if textView.contentSize.height >= self.messageTextViewMaxHeight
{
textView.scrollEnabled = true
}
else
{
textView.frame.size.height = textView.contentSize.height
textView.scrollEnabled = false // textView.isScrollEnabled = false for swift 4.0
}
}
}
This follows a similar approach to the accepted answer but ensures the textView
is fully constrained in both height states.
(There's a bug in the accepted answer - using a height constraint with a <=
relation is insufficient to fully constrain the textView
when scrolling is enabled, since in this case the view provides no intrinsicContentSize
. You can see this in IB (with scrolling disabled), or at runtime via view debugging.)
This is all that's necessary:
// In IB, set the relation to `=` and the constant to your desired threshold point
// Notice this is a strong reference (since the constraint may get deactivated)
@IBOutlet var textViewHeightConstraint: NSLayoutConstraint!
func textViewDidChange(textView: UITextView)
{
let isOversize = textView.contentSize.height >= textViewHeightConstraint.constant
textViewHeightConstraint.isActive = isOversize
textView.isScrollEnabled = isOversize
}
There's no need to set frames manually, since in both cases auto-layout has us covered.
Create a class that inherits from UITextView and add the following into the class:
class CustomTextView: UITextView, UITextViewDelegate {
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
delegate = self
}
var maxHeight: CGFloat = 200
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
if size.height > maxHeight {
size.height = maxHeight
isScrollEnabled = true
} else {
isScrollEnabled = false
}
return size
}
override var text: String! {
didSet {
invalidateIntrinsicContentSize()
}
}
func textViewDidChange(_ textView: UITextView) {
invalidateIntrinsicContentSize()
}
}
Note: - You can initialize maxHeight to infinity and set maxHeight after creating the CustomTextView. This class can be reused anywhere it is needed in the app, and the max height can be modified for different scenarios.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With