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
    }()
  • 1
    If you are familiar with Objective-C, then [this question/answer](http://stackoverflow.com/questions/32836240/how-to-increase-uitextview-height-according-to-text-length-like-whatsapp) might be helpful... – Ahmad F Feb 14 '17 at 20:19
  • 1
    Another option is to use a table view instead of a text view. – mcphersonjr Feb 14 '17 at 20:52
  • 1
    Try creating the uitextview as is but without limiting the max number of lines. Then in textViewDidChange calculate when your number of lines exceeds 5 and change isScrollEnabled to true there. – Andrew McKinley Feb 14 '17 at 21:25
  • scroll that textView give that not actually scroll, it just expand – Gennadii Tsypenko Feb 14 '17 at 21:36
  • have you found an answer to this question? – Andrey Nov 19 '19 at 03:48

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.
  • 428
  • 3
  • 22
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
  • 315
  • 2
  • 10