问题
You can download a sample project demonstrating the issue below here: https://github.com/DimaVartanian/keyboard-extension-height-bug
When creating a keyboard extension and not specifying a concrete height for its components but instead anchoring them to the view/inputView so that in theory the system will determine their height based on environment and orientation, in some situations that height instead turns into 0 and the keyboard is crushed (with the exception of anything that has a concrete height such as a self sized label or button).
This only seems to occur on iOS 10. On iOS 9, the child views resized correctly to fit the default automatic keyboard height.
There are several scenarios this can manifest and this project demonstrates a basic one. It starts with the basic keyboard extension template with the default "next keyboard" button and the 2 size constraints it comes with:
self.nextKeyboardButton.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
self.nextKeyboardButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
Next, we create a single other view that we want to fill the space of the superview without defining a concrete size for itself:
let anotherView = UIView()
anotherView.backgroundColor = UIColor.red
anotherView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(anotherView)
anotherView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
anotherView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
anotherView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
Now, let's say we just want to anchor this new view to the bottom of our keyboard superview. We would just do something like:
anotherView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
The result looks like this:
iOS 9
iOS 10
This layout is exactly what we expect. Now instead, let's anchor the new view to the top of our next keyboard button. We get rid of the constraint we just added and replace it with
anotherView.bottomAnchor.constraint(equalTo: self.nextKeyboardButton.topAnchor).isActive = true
Logically, the resulting height should be the same (determined by the system)
The result is now this:
iOS 9
iOS 10
On iOS 9 it behaves as expected but on iOS 10, the flexible height view is resized down to 0 and all that is left is the fixed height button.
There are no messages about conflicting constraints. I'm trying to figure out what could be causing this and why it would only be happening on iOS 10.
回答1:
Apple has responded to my DTS ticket and told me to file a bug report, so this is actually an iOS 10 bug. I have filed a radar (#28532959) and will update this answer if I ever get a response. If someone else comes up with a concrete solution that allows me to still use autolayout to achieve an automatic height, answers are still accepted.
回答2:
Here's my workaround. It is a little laggy when the device rotates, but it will do the job until Apple fixes this bug. I first thought it had something to do with inputView.allowSelfSizing
, but that variable didn't seem to change anything.
First, declare heightConstraint
:
var heightConstraint: NSLayoutConstraint!
In viewDidLoad
, Add your custom view:
let nibName: String! = UIDevice.isPhone ? "KeyboardViewiPhone" : "KeyboardViewiPad"
customView = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! UIView
customView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(customView)
Add a constraint for the width as you would do normally:
let widthConstraint = NSLayoutConstraint(item: view, attribute: .width, relatedBy: .equal, toItem: customView, attribute: .width, multiplier: 1.0, constant: 0.0)
Add a constant constraint for the height:
heightConstraint = NSLayoutConstraint(item: customView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: view.frame.height)
view.addConstraints([widthConstraint, heightConstraint])
Now comes the fix:
override func viewDidLayoutSubviews() {
heightConstraint.constant = view.bounds.height
}
As viewDidLayoutSubviews
is called every time view.bounds
changes, it will handle orientation changes correctly.
回答3:
I also faced the same issue. this is because of the Autolayout Constraints. Just remove all constraints. and set auto resizing.
回答4:
I got it solved by setting a new constrain for the height.
回答5:
I have also faced the same problem for the custom keyboard extension in Xcode 8.2. This is caused by the auto resizing
. In my case, I solved this in the below manner.
Initially, my custom keyboard have 3 views. In this, I was fixed the trailing, leading, top and height for the first and last view. And place the middle view like in the image.
after that select the middle view and open the show the size inspector
in the storyboard. In the size inspector,
you will find an option auto resizing
. In that select the constraint indicators for that view.
After selecting that you run your project in a device and it will work correctly without missing any view.
Note: - It will work for both portrait and landscape modes. And mainly you don't have to give constraints for the middle view.
回答6:
IMHO, best working solution is using "Proportional Height". For example, in my case, I finally ended with 2 views. Top one got 0.8 of height of superview, bottom - 0.2. It's not perfect solution, but you can still benefits from autolayout.
来源:https://stackoverflow.com/questions/39694039/keyboard-extension-loses-height-in-ios-10-when-trying-to-size-automatically-in-s