I have a customized keyboard created by code, it is a unique input view for a specific textfield. I implement this in my project:
let keyboardContainerView = KBContainerView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height*0.5))
keyboardContainerView.addSubview(myKeyboardView)
textfield.inputView = keyboardContainerView
The KBContainerView is a UIView but has a function, that is when detected device rotation, the frame change. It's quite simple.
override init(frame: CGRect) {
super.init(frame: frame)
NotificationCenter.default.addObserver(self, selector: #selector(updateFrame), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@objc func updateFrame() {
self.frame = CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height*0.5)
}
But I found that though the keyboard container view is changed, as I printed it on the command line but the size of keyboard seems does not change. Here is a gif.
Start from a landscape view does not change the height either.
To fix this problem I tried to use autoresizingMasks
on the input view but things get worse, the keyboard height is wrong when starts the app. The navigation bar also covered keyboard in landscapeview.
In my project, I did not wrote a UIKeyboardviewController
for simplicity. What I am trying to achieve is that when rotating my device, the keyboard can takes half space of the screen. (height is 0.5 * screen height)
Is it because I wrote the change size action in the wrong place?
Usually I get use the standard keyboard dimensions for my custom inputView
using
autoresizingMask = [.flexibleWidth, .flexibleHeight]
In this case, if you want it always to be 50% of the height, you might want to
translatesAutoresizingMaskIntoConstraints
;For example, below is a simple input view that I've defined to be 50% of the height of the window with the following within the keyboard input UIView
subclass:
override func didMoveToSuperview() {
super.didMoveToSuperview()
translatesAutoresizingMaskIntoConstraints = false
guard let superview = superview else { return }
var lastView: UIView! = self
while lastView.superview != nil {
lastView = lastView.superview
}
NSLayoutConstraint.activate([
heightAnchor.constraint(equalTo: lastView.heightAnchor, multiplier: 0.5, constant: 0),
widthAnchor.constraint(equalTo: superview.widthAnchor),
centerXAnchor.constraint(equalTo: superview.centerXAnchor),
bottomAnchor.constraint(equalTo: superview.bottomAnchor)
])
}
Now I'm crawling up the view hierarchy to get the top level view. Perhaps you'd want to pass it the view that you want it to use for the height constraint. I just hate referring to UIScreen.main
because sometimes our app won't have the full screen.
But let's not get lost in the details. The key is to use constraints and let the auto layout engine do everything for us. Then we don't have to respond to rotation events ourselves: