how can i increase the height of an inputAccessoryView
Asked Answered
O

2

19

I have spent several days on this with no solution in sight.

I have an inputAccessoryView which consists of a UIView containing a textView and two buttons. The behaviour of the inputAccessoryView is as expected and works fine in all cases except one.

When the height of the textView increases, I am trying to increase the height of the inputAccessoryView by the same amount. When I redefine the height of the inputAccessoryView in textViewDidChange, the inputAccessoryView increases height downwards over the keyboard instead of upwards.

I have tried many different suggestions from SO but nothing has worked. I guess it is the automatically added NSLayoutConstraint of the inputAccessoryView but I have no idea how to change that value in swift and iOS 8.3.

func textViewDidChange(textView: UITextView) {

    var contentSize = messageTextView.sizeThatFits(CGSizeMake(messageTextView.frame.size.width, CGFloat.max))

    inputAccessoryView.frame.size.height = contentSize.height + 16

}

adding

inputAccessoryView.setTranslatesAutoresizingMaskIntoConstraints(true)

to the above code helps and the inputAccessoryView height increases upwards correctly however I get Unable to simultaneously satisfy constraints for several constraints and it is very difficult to identify the offenders. Also I get an odd effect of the textView creating extra space below on every second instance of a new line.

thanks.

Olein answered 5/8, 2015 at 2:37 Comment(1)
i've noticed the first call of textViewDidChange does correctly resize the inputAccessoryView without the setTranslatesAutoresizingMaskIntoConstraints line, but subsequent calls do not have any effect. I wonder why that is and how i can restore it to that initial state everytimeOlein
S
54

To make input accessory view grow vertically you just set its autoresizingMask = .flexibleHeight, calculate its intrinsicContentSize and let the framework do the rest.

The code:

class InputAccessoryView: UIView, UITextViewDelegate {

    let textView = UITextView()

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

        // This is required to make the view grow vertically
        self.autoresizingMask = UIView.AutoresizingMask.flexibleHeight

        // Setup textView as needed
        self.addSubview(self.textView)
        self.textView.translatesAutoresizingMaskIntoConstraints = false
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[textView]|", options: [], metrics: nil, views: ["textView": self.textView]))
        self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[textView]|", options: [], metrics: nil, views: ["textView": self.textView]))

        self.textView.delegate = self

        // Disabling textView scrolling prevents some undesired effects,
        // like incorrect contentOffset when adding new line,
        // and makes the textView behave similar to Apple's Messages app
        self.textView.isScrollEnabled = false
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var intrinsicContentSize: CGSize {
        // Calculate intrinsicContentSize that will fit all the text
        let textSize = self.textView.sizeThatFits(CGSize(width: self.textView.bounds.width, height: CGFloat.greatestFiniteMagnitude))
        return CGSize(width: self.bounds.width, height: textSize.height)
    }

    // MARK: UITextViewDelegate

    func textViewDidChange(_ textView: UITextView) {
        // Re-calculate intrinsicContentSize when text changes
        self.invalidateIntrinsicContentSize()
    }

}
Shorter answered 18/9, 2015 at 9:8 Comment(4)
Thank you for a very concise answer.Olein
How did you know how to do this? It's like magic how it just works! I'd love to know the process you went through to learn this technique.Zonnya
in iOS 11, this method only works when the text entered causes the UITextBox to grow. When shrinking, it stays the same size.Kweiyang
Just in case anyone is new here, it's override var intrinsicContentSize: CGSize { ... } and autoresizingMask = .flexibleHeight in the current swift version (4.2). Great answer BTWDriftage
G
4

Fast forward to 2020, you can just do the following, everything else the same as in maxkonovalov's answer

override var intrinsicContentSize: CGSize {
    return .zero
}

// MARK: UITextViewDelegate

func textViewDidChange(_ textView: UITextView) {
    sizeToFit()
}
Giovannagiovanni answered 14/3, 2020 at 23:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.