问题
I have iOS custom keyboard that changes height when it rotates.
My code works fine 95% times... But in some cases (see below) the height is not changed when rotated to landscape - portrait height is kept.
Issue can be reproduced with this (almost) minimal code - create new Keyboard Extension target and copy this code to KeyboardViewController
:
class KeyboardViewController: UIInputViewController {
private var orangeView = UIView()
private var heightConstraint: NSLayoutConstraint!
@IBOutlet var nextKeyboardButton: UIButton!
override func updateViewConstraints() {
super.updateViewConstraints()
let screenSize = UIScreen.mainScreen().bounds.size
let screenH = screenSize.height
let screenW = screenSize.width
let isLandscape = !(self.view.frame.size.width == screenW * ((screenW < screenH) ? 1 : 0) + screenH * ((screenW > screenH) ? 1 : 0))
let desiredHeight: CGFloat = isLandscape ? 193 : 252
if heightConstraint.constant != desiredHeight {
heightConstraint!.constant = desiredHeight
orangeView.frame = CGRect(x: 0, y: 0, width: screenW, height: isLandscape ? 193 : 252)
}
}
override func viewDidLoad() {
super.viewDidLoad()
nextKeyboardButton = UIButton(type: .System)
nextKeyboardButton.setTitle("Next Keyboard", forState: .Normal)
nextKeyboardButton.sizeToFit()
nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = false
nextKeyboardButton.addTarget(self, action: "advanceToNextInputMode", forControlEvents: .TouchUpInside)
heightConstraint = NSLayoutConstraint(item:self.inputView!, attribute:.Height, relatedBy:.Equal, toItem:nil, attribute:.NotAnAttribute, multiplier: 0.0, constant: 0) //preparing heightConstraint
heightConstraint?.priority = 999
orangeView.backgroundColor = UIColor.orangeColor()
view.addSubview(orangeView)
view.addSubview(self.nextKeyboardButton)
let nextKeyboardButtonLeftSideConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0)
let nextKeyboardButtonBottomConstraint = NSLayoutConstraint(item: self.nextKeyboardButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
view.addConstraints([nextKeyboardButtonLeftSideConstraint, nextKeyboardButtonBottomConstraint])
}
override func viewWillAppear(animated: Bool) {
if self.view.constraints.filter({c in c == self.heightConstraint}).isEmpty {
self.view.addConstraint(heightConstraint)
}
view.setNeedsUpdateConstraints() //ensures that updateViewConstraints always gets called at least once
super.viewWillAppear(animated)
}
}
For more info on how it works see this and this answer.
When you run the keyboard it will probably work fine - it is slightly higher and after rotation the orange view covers the whole keyboard:
However you might also get this (portrait height is kept after rotation):
Steps to reproduce the isue (with code above):
- Open keyboard in Messages app, rotate landscape and back
- If you did not see the issue kill Messages app (press home button 2x -> swipe messages up)
- Open messages again, rotate landscape and back
- You might need to repeat steps 1-3 few times to see the issue (usually no more than 2-4 times)
What I know:
- If you see the issue you will keep seing it until keyboard is hidden and re-displayed
- If you see the issue hide and re-display the keyboard withing same app - the issue always disapears
- The issue might appear again only after killing and restarting the hosting app
- Debuger shows that
heightConstraint!.constant
is193
but bothview.frame.height
andview.window?.frame.height
are still253
(changing frame directly does not fix it)
What I have tried:
- Instead of just setting the constraint
heightConstraint!.constant = desiredHeight
first remove it fromview
, set new value and then re-add it - I verified that
heightConstraint!.constant
is always changed when it should be
How do I fix or workaround this issue? There has to be a solution because SwiftKey does not have this issue.
回答1:
I faced a similar issue with a keyboard extension -- on iPhone 6+ models, it always failed to set its height correctly on rotations the first time the keyboard was invoked in an app, and occasionally on iPhone 6 and other iPhone models.
I eventually found a solution, though it has its own drawbacks.
Firstly, the documentation states that
In iOS 8.0, you can adjust a custom keyboard’s height any time after its primary view initially draws on screen.
You're setting the height constraint in -[UIViewController viewWillAppear:]
, which, under a strict interpretation of the documentation, is too early. If you set it in -[UIViewController viewDidAppear:]
, the problem that you're currently having should be solved.
However, you may then find that your height adjustment is visually jarring, as it is occurring after the keyboard is appearing.
I have no idea how SwiftKey manages to set their height (seemingly) before the keyboard appears and avoid this issue.
来源:https://stackoverflow.com/questions/36145450/incorrect-keyboard-extension-height-after-rotation