How to Adjust the Height of a Textview to His Content in Swift

How do I size a UITextView to its content?

This works for both iOS 6.1 and iOS 7:

- (void)textViewDidChange:(UITextView *)textView
{
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
}

Or in Swift (Works with Swift 4.1 in iOS 11)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

If you want support for iOS 6.1 then you should also:

textview.scrollEnabled = NO;

How to adjust the height of a textview to his content in SWIFT?

I found a solution.

I was focus on the height of my UITextView, then I read a post talking about the aspect ratio. I wanted to try and that worked!

So in the storyboard, I added an aspect ratio for the textview, and I checked "Remove at build time" option.

In viewDidLayoutSubviews(), I wrote :

override func viewDidLayoutSubviews() {

super.viewDidLayoutSubviews()

let contentSize = self.myTextViewTitle.sizeThatFits(self.myTextViewTitle.bounds.size)
var frame = self.myTextViewTitle.frame
frame.size.height = contentSize.height
self.myTextViewTitle.frame = frame

aspectRatioTextViewConstraint = NSLayoutConstraint(item: self.myTextViewTitle, attribute: .Height, relatedBy: .Equal, toItem: self.myTextViewTitle, attribute: .Width, multiplier: myTextViewTitle.bounds.height/myTextViewTitle.bounds.width, constant: 1)
self.myTextViewTitle.addConstraint(aspectRatioTextViewConstraint!)

}

It works perfectly.

how to make UITextView height dynamic according to text length?

this Works for me, all other solutions didn't.

func adjustUITextViewHeight(arg : UITextView) {
arg.translatesAutoresizingMaskIntoConstraints = true
arg.sizeToFit()
arg.scrollEnabled = false
}

In Swift 4 the syntax of arg.scrollEnabled = false has changed to arg.isScrollEnabled = false.

How can I set the height of a UITextView to exactly match its truncated content?

I expect it's truncated because of your constraints. So you need to calculate the text size in the code and update the constraint value:

let boundingRect = (textView.text as NSString).boundingRect(
with: maxSize,
options: .usesLineFragmentOrigin,
attributes: [ .font: textView.font ],
context: nil
)
heightConstraint.constant = boundingRect.height.rounded(.up)

The result of this operation is float and not related to pixels. When the view size is calculated by the constraints, it get's rounded to pixels (0.5 or 0.333...), that's why we need to round it by ourself to exclude unpredictable cases. To get pixel perfect height you can round it according to screen scale:

textViewHeightConstraint.constant = (boundingRect.height * UIScreen.main.nativeScale).rounded(.up) / UIScreen.main.nativeScale

Also, as @nghiahoang mentioned below, don't forget to zero the insets

textView.textContainerInset = .zero

Here's my sample project

How to adjust the height of the textview depends on the content in correct way?

  1. Assign a height constraint to the text view

  2. Use the following method to change the height:

     func textViewDidChange(_ textView: UITextView) {
    let size = textView.bounds.size
    let newSize = textView.sizeThatFits(
    CGSize(width: size.width, height: CGFloat.greatestFiniteMagnitude)
    )

    if size.height != newSize.height {
    self.userMessageTextViewHeightConstraint.constant = newSize.height
    textView.layoutIfNeeded()
    }
    }

UITextView height to change dynamically when typing / without using storyboards

First make sure your class adopts the UITextViewDelegate protocol so you can be informed when the text changes like this:

class MyClass: UIViewContoller, UITextViewDelegate

Next define this variable somewhere in your class so that you can keep track of the height in a constraint:

var textHeightConstraint: NSLayoutConstraint!

Next add the following constraint and activate it:

    self.textHeightConstraint = addtextview.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true

(if you don't do this in viewDidLoad you need to make textHeightConstraint an optional)

Next subscribe to the delegate (if not already done):

addTextView.delegate = self

Add this function which recalculates the height constraint:

func adjustTextViewHeight() {
let fixedWidth = addtextview.frame.size.width
let newSize = addtextview.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}

Next add a call to that function after the constraints are created to set the initial size:

self.adjustTextViewHeight()

Finally add this method to adjust the height whenever the text changes:

func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}

Just in case that is all confusing here is a minimal example in a sub class of a UIViewController:

class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet var textView: UITextView!
@IBOutlet var textHolder: UIView!

var textHeightConstraint: NSLayoutConstraint!

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
textView.leadingAnchor.constraint(equalTo: textHolder.leadingAnchor, constant: 8).isActive = true
textView.trailingAnchor.constraint(equalTo: textHolder.trailingAnchor, constant: -8).isActive = true
textView.topAnchor.constraint(equalTo: textHolder.topAnchor, constant: 8).isActive = true
textView.bottomAnchor.constraint(equalTo: textHolder.bottomAnchor, constant: -40).isActive = true

self.textHeightConstraint = textView.heightAnchor.constraint(equalToConstant: 40)
self.textHeightConstraint.isActive = true

self.adjustTextViewHeight()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

func textViewDidChange(_ textView: UITextView) {
self.adjustTextViewHeight()
}

func adjustTextViewHeight() {
let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
self.textHeightConstraint.constant = newSize.height
self.view.layoutIfNeeded()
}
}


Related Topics



Leave a reply



Submit