How to Size a Uitextview to Its Content

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 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 do I size a UITextView to its content on iOS 7?

I favor this minimal code change: Just add these two lines after addSubview and before grabbing the height of the frame

...
[scrollView1 addSubview: myTextView];

[myTextView sizeToFit]; //added
[myTextView layoutIfNeeded]; //added

CGRect frame = myTextView.frame;
...

This is tested backwards compatible with iOS 6. NOTE that it shrink-wraps the width. If you're just interested in the height and have a fixed width, just grab the new height but set the original width, and it works just as before on both iOS 6 and 7.

(Speculation: it does size to fit on iOS 7 as well, but the layout is updated later or in a separate thread, and that this forces the layout immediately so that its frame is updated in time for using its height value a few lines later in the same thread.)

NOTES:

1) You might or might not have implemented the outer container resize this way. It does seem to be a common snippet, though, and I've used it in my projects.

2) Since sizeToFit seems to work as expected on iOS 7, you likely don't need the premature addSubView. Whether it will still work on iOS 6 then is untested by me.

3) Speculation: The extra layoutIfNeeded mid-thread might be costly. The alternative as I see it is to resize the outer container on the layout callback (fired or not depending on if the OS decides whether layout is needed or not) where the outer container resize will cause another layout update. Both updates might be combined with other layout updates to be more efficient. If you do have such a solution and you can show that it is more efficient, add it as answer and I'll be sure to mention it here.

Get the content height of a UITextView

You can simply use following method to get the content size:

let contentSize = self.textView.sizeThatFits(self.textView.bounds.size)

Then update the textview frame accordingly:

self.textView.frame = CGRect(width: contentSize.width, height: contentSize.height)

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 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.



Related Topics



Leave a reply



Submit