3

There are several SO answers about how to change Custom Keyboard height. Some of them work for example here but those that work lead to constrains conflict error printed to console output:

Unable to simultaneously satisfy constraints... 
Will attempt to recover by breaking constraint...

Here is my very simple keyboard controller that sets custom keyboard height (is Swift):

class KeyboardViewController: UIInputViewController {
    private var heightConstraint: NSLayoutConstraint?
    private var dummyView: UIView = UIView()

    override func updateViewConstraints() {
        super.updateViewConstraints()

        if self.view.frame.size.width == 0 || self.view.frame.size.height == 0 || heightConstraint == nil {
            return
        }
        inputView.removeConstraint(heightConstraint!)
        heightConstraint!.constant = UIInterfaceOrientationIsLandscape(self.interfaceOrientation) ? 180 : 200
        inputView.addConstraint(heightConstraint!)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dummyView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.addSubview(self.dummyView)

        view.addConstraint(NSLayoutConstraint(item: self.dummyView, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0))
        view.addConstraint(NSLayoutConstraint(item: self.dummyView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0))

        heightConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
    }
}

This produces the annoying output error that my constrain heightConstraint that I added in updateViewConstraints is in conflict with constrain identified as UIView-Encapsulated-Layout-Height.

I tried to remove conflicting constant (UIView-Encapsulated-Layout-Height) in updateViewConstraints as follows:

let defaultHeightConst = inputView.constraints().filter() {c in (c as? NSLayoutConstraint)?.identifier == "UIView-Encapsulated-Layout-Height"}.first as? NSLayoutConstraint
if defaultHeightConst != nil {
    inputView.removeConstraint(defaultHeightConst!
}

This did not help, the output warning is still there. How do I solve this? Specifically, what can I do to get rid of the output error message?

Community
  • 1
  • 1
Rasto
  • 17,204
  • 47
  • 154
  • 245
  • did you get rid of the output warnings??? – Ezimet Oct 28 '14 at 17:10
  • @Ezimet Yes, unsuprisingly I got rid of the output warning. What is very suprising is that the constant with priority 990 is still honered not overriden by higher priority default height constant (with which it was in conflict before). Care to explain why is that to me? – Rasto Oct 30 '14 at 04:10

2 Answers2

3

Try setting heightConstraint priority to less than 1000. Some thing like blow :

heightConstraint.priority = 990

OR

heightConstraint.priority = 999
Ezimet
  • 5,058
  • 4
  • 23
  • 29
  • The option `heightConstraint = 990` actually works, the `heightConstraint = UILayoutPriorityDefaultHigh` will not compile. – Rasto Oct 30 '14 at 10:32
  • Edited my answer . Actually priority 999 or 990 all works for you. these priorities are almost as high as the 1000 Required priority so they will not be easily effected. – Ezimet Oct 30 '14 at 11:40
  • When I set this my app crashes :( – Vishnu Kumar. S Dec 08 '15 at 12:48
  • If you do that, then your constraint will not be taken in account, as its priority will be less than the automatically generated one. Even if the author told it worked, it did not for me — and I cannot explain why it worked for him… – Steve G. May 31 '20 at 10:23
2

This warning is still a problem in iOS 13.

It appears because the view of the keyboard extension (KeyboardViewController’s view property) translates autoresizing mask into constraints.

What you want is removing the automatically generated height constraint by calling:

view.translatesAutoresizingMaskIntoConstraints = false

Nevertheless, this is not enough: you have to replace the important generated constraints.

I did that in the viewWillAppear function, as the parent view exists at this moment. I use the constraintHaveBeenAdded property to avoid to add several times the same constraints, as the function can be called repeatedly.

class KeyboardViewController: UIInputViewController {

  private var constraintsHaveBeenAdded = false

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    initKeyboardConstraints()
  }

  private func initKeyboardConstraints() {
    if constraintsHaveBeenAdded { return }
    guard let superview = view.superview else { return }
    view.translatesAutoresizingMaskIntoConstraints = false
    view.leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
    view.rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true
    view.heightAnchor.constraint(equalToConstant: 250.0).isActive = true
    constraintsHaveBeenAdded = true
  }

}

You can even remove the height constraint and let the subviews constraint decide of the keyboard height.

Steve G.
  • 589
  • 5
  • 13