[英]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.