Bigair Bigair - 9 months ago 45
iOS Question

Adjusting height of UITextView to its text does not work properly

I wrote following code to fit UITextView's height to its text.

The size changes but top margin relative to first line of text differ every other time when I tap enter key on keyboard to add new line.


  • xCode 7.3

  • Deployment target: iOS 9

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

lazy var textView: UITextView = {
let tv = UITextView(frame: CGRectMake(20, 200, (self.view.frame.width - 40), 0) )
tv.backgroundColor = UIColor.lightGrayColor()
return tv

override func viewDidLoad() {

view.addSubview( textView )

textView.delegate = self
let height = self.height(textView)
let frame = CGRectMake(textView.frame.origin.x, textView.frame.origin.y, textView.frame.width, height)
textView.frame = frame

func textViewDidChange(textView: UITextView) {

let frame = CGRect(x: textView.frame.origin.x, y: textView.frame.origin.y, width: textView.frame.width, height: height(textView) )
textView.frame = frame

func height(textView: UITextView) -> CGFloat {
let size = CGSizeMake(textView.frame.size.width, CGFloat.max)
let height = textView.sizeThatFits(size).height
return height

enter image description here
enter image description here

I tried few other ways to fit UITextView height but they just acted the same say.

Answer Source

To fix this, subclass UITextView and override setContentOffset to allow scrolling only if the content height is larger than the intrinsic content height. Something like:

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool) {
    let allowScrolling = (contentSize.height > intrinsicContentSize.height)
    if allowScrolling {
        super.setContentOffset(contentOffset, animated: animated)

For auto-growing dynamic height text view, the caret moves on starting a new line. At this moment, the size of the text view hasn't grown to the new size yet. The text view tries to make the caret visible by scrolling the text content which is unnecessary.

You may also need to override intrinsicContentSize too.