7

I have an app which has chatting functionality where UITextview is used for entering the message. UITextview height has to be dynamic (if user enters the message, the height has to be changed according to the text length till a specific Height).

How can I achieve this?

Eimantas
  • 48,927
  • 17
  • 132
  • 168
Midhun Narayan
  • 829
  • 2
  • 9
  • 26

5 Answers5

14

Disable Scrolling of textView.

enter image description here

enter image description here

TO Increase Height to a specific value and then enable scrolling.

Provide a maximum height constraint then add this code to your viewController

 class YourViewController: UIViewController, UITextViewDelegate
    {
        @IBOutlet weak var yourTextView: UITextView!

        let textViewMaxHeight: CGFloat = 100
        override func viewDidLoad()
        {
            super.viewDidLoad()
            yourTextView.delegate = self
        }

        func textViewDidChange(textView: UITextView)
        {
            if textView.contentSize.height >= self.textViewMaxHeight
            {
                textView.scrollEnabled = true
            }
            else
                {
                textView.frame.size.height = textView.contentSize.height
                textView.scrollEnabled = false
            }
        }
    }
Anuraj
  • 1,242
  • 10
  • 25
7

Add a height constraint to your textView and create an outlet so you can adjust it. Then you can use the UITexfield delegate method textViewDidChange(_ textView: UITextView) to adjust the height.

func textViewDidChange(_ textView: UITextView) {

    // get the current height of your text from the content size
    var height = textView.contentSize.height

    // clamp your height to desired values
    if height > 90 {
        height = 90
    } else if height < 50 {
        height = 50
    }

    // update the constraint
    textViewHeightConstraint.constant = height
    self.view.layoutIfNeeded()
}

shorter version...

func textViewDidChange(_ textView: UITextView) {
    let maxHeight: CGFloat = 90.0
    let minHeight: CGFloat = 50.0
    textViewHeightConstraint.constant = min(maxHeight, max(minHeight, textView.contentSize.height))           
    self.view.layoutIfNeeded()
}
pkorosec
  • 676
  • 8
  • 13
4

In case you are subclassing UITextView this could be a solution as well:

class Message: UITextView {


    var maximalSizeNotScrollable: CGFloat = 200
    var minimumHeightTextView: CGFloat = 35

    var textViewHeightAnchor: NSLayoutConstraint!


    override var contentSize: CGSize {
        didSet {

            if textViewHeightAnchor != nil {
                textViewHeightAnchor.isActive = false

            }
            textViewHeightAnchor = heightAnchor.constraint(equalToConstant: min(maximalSizeNotScrollable, max(minimumHeightTextView, contentSize.height)))
            textViewHeightAnchor.priority = UILayoutPriority(rawValue: 999)

            textViewHeightAnchor.isActive = true
            self.layoutIfNeeded()
        }
    }
}

The priority needs to be smaller than 1000 otherwise you will encounter problems with _UITemporaryLayoutHeight.

PaFi
  • 888
  • 1
  • 9
  • 24
2

I was struggling with the same problem. After reading @Anuraj's response, I dragged and dropped the height constraint of the UITextView to view controller because when textview reaches to the max height and when the scroll is enabled textview was getting smaller just to display one line, so I found the solution by giving the max height to the height constraint of textview. Textview will expand until it reaches max height, after that it will be scrollable. When you delete text, textview height will get smaller automatically.

@IBOutlet weak var txMessageHeight: NSLayoutConstraint!    
let textViewMaxHeight: CGFloat = 120

func textViewDidChange(_ textView: UITextView) {
    if textView.contentSize.height >= self.textViewMaxHeight{
        txMessageHeight.constant = self.textViewMaxHeight
        textView.isScrollEnabled = true
    }else{
        textView.frame.size.height = textView.contentSize.height
        textView.isScrollEnabled = false
    }
}
0

Set the Height Constraint of the TextView to <= 120(maxHeight) in StoryBoard

enter image description here

func textViewDidChange(_ textView: UITextView) {
        if textView.contentSize.height >= maxHeight {
            textView.isScrollEnabled = true
        } else {
            textView.isScrollEnabled = false
        }
    }

And if you want to reset the height of TextView when its empty, you can just write

UIView.animate(withDuration: 0.15) {
   self.view.layoutIfNeeded()
}

Simran Singh
  • 445
  • 6
  • 8