Search code examples
uikitios-autolayout

Autolayout issue with dynamically sized, scrolling-enabled UITextView


Here is what I want:

+-------------------------+   +-------------------------+
| +---------------------+ |   | +---------------------+ |
| |        UILabel      | |   | |        UILabel      | |
| +---------------------+ |   | +---------------------+ |
|                         |   |                         |
| +---------------------+ |   | +---------------------+ |
| | UITextView; height  | |   | | UITextView; height || |
| | depends on content  | |   | | depends on content || |
| +---------------------+ |   | | This one here has  || |
|                         |   | | so much text that   | |
| +---------------------+ |   | | the complete text   | |
| |       UIButton      | |   | | can only be seen by | |
| +---------------------+ |   | | scrolling: Text Te… | |
|                         |   | +---------------------+ |
|                         |   |                         |
|                         |   | +---------------------+ |
|                         |   | |       UIButton      | |
|                         |   | +---------------------+ |
+-------------------------+   +-------------------------+

All elements live on a plain UIView.

The UILabel and the UIButton have a fixed height. The UITextView should only be as tall as its content. Even for very long text its height should never push the following elements off the screen.

What I have so far:

  • UILabel's top is constrained to its superviews top (=0)
  • UITextView's top is constrained to the UILabel's bottom (=0)
  • UIButton's top is constrained to the UITextView's bottom (=0)
  • UIButton's bottom is constrained to its superviews bottom (>=0)
  • UITextView has scrolling enabled
  • UITextView has intrinsic height set
  • UITextView Content Compression Resistance: 1000
  • UITextView Content Hugging Priority: 1

With this setup the UITextView is not shown at all. If I set a minimum height for the UITextView it is displayed with this height but the height does not adjust to the content. If I disable scrolling the height of the UITextView is properly adjusted.

Can I have a content-aware, scrolling UITextView? Can this be accomplished via AutoLayout? If yes, how?


Solution

  • There is, unfortunately, no "auto" method of enabling/disabling UITextView scrolling in the manner you want.

    One option is to determine the max-height for your text view, and then use an observer to watch for changes in the text view's contentSize. When the contentSize height exceeds your max-height, enable scrolling. See this answer for additional details (along with a link to an example project): Expanding UITextView inside a Stack View with scrolling enabled

    Another option is to embed a non-scrolling UITextView in a scrollable UIScrollView. The trick is to constrain the scrollview's height to the height of the text view, but give it a Priority of 250. Setup all other constraints as normal. The scrollview's height will expand to match the text view's height as it changes, but the other constraints will restrict it so it doesn't keep growing.