Is there a good way to adjust the size of a UITextView
to conform to its content? Say for instance I have a UITextView
that contains one line of text:
"Hello world"
I then add another line of text:
"Goodbye world"
Is there a good way in Cocoa Touch to get the rect
that will hold all of the lines in the text view so that I can adjust the parent view accordingly?
As another example, look at the notes' field for events in the Calendar application - note how the cell (and the UITextView
it contains) expands to hold all lines of text in the notes' string.
To make a dynamically sizing
UITextView
inside aUITableViewCell
, I found the following combination works in Xcode 6 with the iOS 8 SDK:UITextView
to aUITableViewCell
and constrain it to the sidesUITextView
'sscrollEnabled
property toNO
. With scrolling enabled, the frame of theUITextView
is independent of its content size, but with scrolling disabled, there is a relationship between the two.If your table is using the original default row height of 44 then it will automatically calculate row heights, but if you changed the default row height to something else, you may need to manually switch on auto-calculation of row heights in
viewDidLoad
:For read-only dynamically sizing
UITextView
s, that’s it. If you’re allowing users to edit the text in yourUITextView
, you also need to:Implement the
textViewDidChange:
method of theUITextViewDelegate
protocol, and tell thetableView
to repaint itself every time the text is edited:And don’t forget to set the
UITextView
delegate somewhere, either inStoryboard
or intableView:cellForRowAtIndexPath:
Swift answer: The following code computes the height of your textView.
Now you can set the height of your textView to
myTextHeight
The following things are enough:
UITextView
:You may even use
UITableViewAutomaticDimension
.In my (limited) experience,
does not respect newline characters, so you can end up with a lot shorter
CGSize
than is actually required.does seem to respect the newlines.
Also, the text isn't actually rendered at the top of the
UITextView
. In my code, I set the new height of theUITextView
to be 24 pixels larger than the height returned by thesizeOfFont
methods.In iOS6, you can check the
contentSize
property of UITextView right after you set the text. In iOS7, this will no longer work. If you want to restore this behavior for iOS7, place the following code in a subclass of UITextView.I will post right solution at the bottom of the page in case someone is brave (or despaired enough) to read to this point.
Here is gitHub repo for those, who don't want to read all that text: resizableTextView
This works with iOs7 (and I do believe it will work with iOs8) and with autolayout. You don't need magic numbers, disable layout and stuff like that. Short and elegant solution.
I think, that all constraint-related code should go to
updateConstraints
method. So, let's make our ownResizableTextView
.The first problem we meet here is that don't know real content size before
viewDidLoad
method. We can take long and buggy road and calculate it based on font size, line breaks, etc. But we need robust solution, so we'll do:CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];
So now we know real contentSize no matter where we are: before or after
viewDidLoad
. Now add height constraint on textView (via storyboard or code, no matter how). We'll adjust that value with ourcontentSize.height
:The last thing to do is to tell superclass to
updateConstraints
.Now our class looks like:
ResizableTextView.m
Pretty and clean, right? And you don't have to deal with that code in your controllers!
But wait! Y NO ANIMATION!
You can easily animate changes to make
textView
stretch smoothly. Here is an example: