iosswiftnslayoutconstraintautoresizingmaskinputaccessoryview

how can i increase the height of an inputAccessoryView


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.


Solution

  • 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()
        }
    
    }