![](/img/trans.png)
[英]Handling external keyboard presses without showing keyboard on screen on iOS app
[英]iOS - position view set distance from bottom of screen or keyboard (if it is showing) without subscribing to keyboard notifications
在Android中,您可以使用RelativeLayout
并使用layout_alignParentBottom
将视图(例如按钮)固定到其底部。 当键盘出现时,视图将在其上方。
有没有一种方法可以在iOS中做到这一点, 而无需订阅键盘事件并根据键盘高度调整视图的约束?
我问是因为我看到的所有示例都订阅了键盘事件。 但这从我的经验来看是相当错误的。 您不仅必须订阅键盘事件,还必须订阅应用程序范围的事件。
编辑:为澄清起见,我正在询问我到底在做什么。 没有添加inputAccessoryView
。 我希望视图(无论是按钮,图像还是其他)始终与屏幕底部保持固定的距离。 当键盘出现时,我希望该视图与键盘顶部的距离相同。 如果键盘消失,则视图将向下移动到其原始位置。
目前没有其他方法。 显示键盘是应用程序范围内的事件,因此设计使然。 您可以获取有关框架更改的通知,然后在需要时相应地布置视图。 有一些工具可以为您提供帮助,例如提到的IQKeyboard,但请注意,此工具在多个iOS版本和/或设备上可能确实存在错误,因此您需要不断更新该库。 它也非常hackhack,但确实不需要很多工作。
通过键盘通知,您可以使用高级工具来简化操作。 我前一段时间使用的是:
import UIKit
protocol KeyboardManagerDidChangeVisibleDelegate: class {
func keyboardManagerChangedKeyboardVisible(sender: KeyboardManager, visible: Bool)
}
protocol KeyboardManagerWillChangeFrameDelegate: class {
func keyboardManagerWillChangeKeyboardFrame(sender: KeyboardManager, from startFrame: CGRect, to endFrame: CGRect)
}
protocol KeyboardManagerDidChangeFrameDelegate: class {
func keyboardManagerDidChangeKeyboardFrame(sender: KeyboardManager, from startFrame: CGRect, to endFrame: CGRect)
}
class KeyboardManager {
var keyboardVisible: Bool = false
var keyboardFrame: CGRect = CGRect.zero
var visibilityDelegate: KeyboardManagerDidChangeVisibleDelegate?
var willChangeFrameDelegate: KeyboardManagerWillChangeFrameDelegate?
var didChangeFrameDelegate: KeyboardManagerDidChangeFrameDelegate?
static var sharedInstance: KeyboardManager = {
let manager = KeyboardManager(isShared: true)
return manager
}()
deinit {
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
convenience init() {
self.init(isShared: false)
}
private init(isShared: Bool) {
attachNotifications()
if isShared == false {
keyboardVisible = KeyboardManager.sharedInstance.keyboardVisible
keyboardFrame = KeyboardManager.sharedInstance.keyboardFrame
}
}
private func attachNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardChange), name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}
@objc private func onKeyboardChange(notification: NSNotification) {
guard let info = notification.userInfo else {
return
}
guard let value: NSValue = info[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
return
}
guard let oldValue: NSValue = info[UIKeyboardFrameBeginUserInfoKey] as? NSValue else {
return
}
let newFrame = value.cgRectValue
self.keyboardFrame = newFrame
let oldFrame = oldValue.cgRectValue
if let durationNumber = info[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, let keyboardCurveNumber = info[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber {
let duration = durationNumber.doubleValue
let keyboardCurve = keyboardCurveNumber.intValue
let curve: UIViewAnimationCurve = UIViewAnimationCurve(rawValue: keyboardCurve) ?? .linear
let options = UIViewAnimationOptions(rawValue: UInt(curve.rawValue << 16))
UIView.animate(withDuration: duration, delay: 0, options: options, animations: {
self.willChangeFrameDelegate?.keyboardManagerWillChangeKeyboardFrame(sender: self, from: oldFrame, to: newFrame)
}, completion: { _ in
self.didChangeFrameDelegate?.keyboardManagerDidChangeKeyboardFrame(sender: self, from: oldFrame, to: newFrame)
})
} else {
self.willChangeFrameDelegate?.keyboardManagerWillChangeKeyboardFrame(sender: self, from: oldFrame, to: newFrame)
self.didChangeFrameDelegate?.keyboardManagerDidChangeKeyboardFrame(sender: self, from: oldFrame, to: newFrame)
}
}
@objc private func onKeyboardWillShow(notification: NSNotification) {
self.keyboardVisible = true
self.visibilityDelegate?.keyboardManagerChangedKeyboardVisible(sender: self, visible: self.keyboardVisible)
}
@objc private func onKeyboardWillHide(notification: NSNotification) {
self.keyboardVisible = false
self.visibilityDelegate?.keyboardManagerChangedKeyboardVisible(sender: self, visible: self.keyboardVisible)
}
}
我在这里所做的订阅将出现委托KeyboardManager.sharedInstance.willChangeFrameDelegate = self
in view将出现在视图控制器的方法中。 那么实现就是:
extension MyViewController: KeyboardManagerWillChangeFrameDelegate {
func keyboardManagerWillChangeKeyboardFrame(sender: KeyboardManager, from startFrame: CGRect, to endFrame: CGRect) {
panelBottomConstraint?.constant = view.bounds.height-max(0, view.convert(endFrame, from: nil).origin.y)
}
}
因此仍然使用约束,但是由于管理器仅导入一次,因此使用时的代码量相对较小。 这应该已经为您的视图以及键盘动画了,这很好。
至于越野车,这个过程从来没有让我失败,但是总的来说,在iOS中使用键盘总是很痛苦,而且很容易产生错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.