4

I'm start implementing text input to a chat app and wondering that is standard behavior of a UITextView with scroll enabled absolutely does not meet expectations.
I want just it is done in chats like WhatsApp. When text reached N, 5 for example lines, scroll bar appear and text container starts scrolling. I wrote code like this, but it doesn't work. As i think needs to count rows in text container and make content insets, or something like this.

   func textViewDidChange(_ textView: UITextView) {
        let fixedWidth = myTextView.frame.size.width
        myTextView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
        let newSize = myTextView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
        var newFrame = myTextView.frame
        let oldFrame = myTextView.frame
        newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
        myTextView.frame = newFrame  
        let shift = oldFrame.height - newFrame.height
        textView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: shift, right: 0)
        textView.scrollIndicatorInsets = textView.contentInset
        textView.scrollRangeToVisible(textView.selectedRange)
    }

And myTextView is specified as:

let myTextView : UITextView = {
        let textView = UITextView()
        textView.translatesAutoresizingMaskIntoConstraints =  false
        textView.isScrollEnabled = false
        textView.textContainer.maximumNumberOfLines = 5
        textView.textContainer.lineBreakMode = .byWordWrapping
        textView.inputAccessoryView = UIView()
        return textView
    }()

2 Answers2

0

Not based on number of lines, but on a user defined height. You'll find your answer here: https://stackoverflow.com/a/51235517/10115072

Daniel Z.
  • 458
  • 1
  • 3
  • 23
0

If you want this behaviour to happen is simple:

  1. Create a UIView having UITextView inside
  2. Create a height constraint in UIView priority 1000 of less than or equal your MAX_HEIGHT and also greater than or equal you MIN_HEIGHT
  3. Create a height constraint in you TextView priority 999 equal to your MIN_HEIGHT
  4. Then add this code to your controller

Code:

class YourViewController: KUIViewController {
    @IBOutlet weak var textView: UITextView!
    override func viewDidLoad() {
        super.viewDidLoad()
        textView.delegate = self
        textView.isScrollEnabled = true
    }
}
extension YourViewController: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        let size = CGSize(width: view.frame.width, height: .infinity)
        let estimatedSize = textView.sizeThatFits(size)
        textView.constraints.forEach { (constraint) in
            if constraint.firstAttribute == .height {
                constraint.constant = estimatedSize.height
            }
        }
    }
}

This has the same behaviour as WhatsApp textView

ERP
  • 325
  • 2
  • 11