简体   繁体   中英

Swift 3: UITextView - Dynanmic height - Programmatically

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?

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

}

}

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, 在此处输入图片说明

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!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM