Incorrect Keyboard Extension height after rotation

狂风中的少年 提交于 2019-12-23 04:54:22

问题


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):

  1. Open keyboard in Messages app, rotate landscape and back
  2. If you did not see the issue kill Messages app (press home button 2x -> swipe messages up)
  3. Open messages again, rotate landscape and back
  4. 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 is 193 but both view.frame.height and view.window?.frame.height are still 253 (changing frame directly does not fix it)

What I have tried:

  • Instead of just setting the constraint heightConstraint!.constant = desiredHeight first remove it from view, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!