Swift 3: UITextView - Dynanmic height - Programmat

2020-03-31 05:13发布

问题:

I have a keyboardContainer class (Subclass of UIView / created programmatically so no storyboard) including a UITextView for the user to type messages in. It is used within a Chat log class and set as the inputAccessoryView. I want to dynamically change the height of it when the user is typing.

I searched for answers and found some. However, I didn't get most of them as they didn't work for me.

What do I have to implement to get the effect I want to have?

Thank´s for your help!

EDIT:

First of all thank you for your help!

However, I´m pretty new to coding so I could not solve the issue. I guess it has something to do with the way I created my keyboardContainer class and its constraints...

Here is the relevant code from within my keyboard container class:

 let textField:UITextView = {
    let view = UITextView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.layer.cornerRadius = 15
    view.layer.masksToBounds = true
    view.font = UIFont.systemFont(ofSize: 15)
    view.backgroundColor = .white
    return view
}()

overried init(frame: CGRect){
super.init(frame: frame)

addSubview(textField)
    textField.leftAnchor.constraint(equalTo: leftButton, constant: 5).isActive = true
    textField.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true

    textFieldHeightAnchor = textField.heightAnchor.constraint(equalTo: heightAnchor, constant: -10)
    textFieldHeightAnchor.isActive = true

    textFieldRightAnchor = textField.rightAnchor.constraint(equalTo: rightAnchor, constant: -85)
    textFieldRightAnchor.isActive = true
}

Inside my ChatLog I´m using this:

 lazy var keyboard: KeyboardContainer = {
    let key = KeyboardContainer()
    key.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 45)
    key.sendButton.addTarget(self, action: #selector(handleSend), for: .touchUpInside)
    return key
}()

override var inputAccessoryView: UIView?{
    get{
        return keyboard
    }
}

What do I need to change ? I guess the constraints?

回答1:

You can make your textView conform to the UITextViewDelegate and then resize it to it's contentSize.

Make your view controller conform to the delegate

class ViewController: UIViewController, **UITextViewDelegate** { ... 

After that

yourTextView.delegate = self // put that in viewDidLoad()

Then you can implement the textViewDidChange method. That means, every time you enter something into the keyboard, this function is called.

func textViewDidChange(_ textView: UITextView) {


if textView == youTextView {

    let currentHeight = textView.frame.size.height

    textView.frame.size.height = 0 // you have to do that because if not it's not working with the proper content size

    textView.frame.size = textView.contentSize // here you detext your textView's content size and make it resize.

    let newHeight = textView.frame.size.height

    let heightDifference = newHeight - currentHeight // get the height difference from before and after editing

    yourContainerView.frame.size.height += heightDifference

}

}



回答2:

Just disable the scrolling. Don't set any other constraints. This might help you with this.

In your viewDidLoad method,

    YourTextView.translatesAutoresizingMaskIntoConstraints = true
    YourTextView.sizeToFit()
    YourTextView.isScrollEnabled = false
    YourTextView.delegate = self
    YourTextView.isEditable = true

Then use UITextViewDelegate and,

func textViewDidChange(_ textView: UITextView) {

    MyTextView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 100)
    MyTextView.translatesAutoresizingMaskIntoConstraints = true
    MyTextView.sizeToFit()
    MyTextView.isScrollEnabled = false

}

This was before the change,

This was after,



回答3:

If you are looking for UITextView like message app. No more deal with code you can manage it using constraints. It is better way to do this using constraints rather then deal with more coding.

Here is the step by step explanation of this.

Step : 1

  • Arrange UItextView and UIBUtton inside one UIView and give height constraint to UIView with low priority.

Step : 2

  • Also give height constraint to UITextView with Greater Then or Equal. as image represent it.

Step : 3

Now you just have to deal with contentSize and isScrollEnabled as below snippet.

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool{
if (textView.contentSize.height < 150){
    textView.isScrollEnabled = false
   }
   else{
     textView.isScrollEnabled = true
   }
  return true
}

Hope this help you!!