是否可以将键盘向上移动,以便它不会覆盖UITabViewController的TabBar?
答案 0 :(得分:1)
如果您主要关注的是让用户关闭键盘,那么平台上通常会应用一些众所周知的模式:
有关UI 的假设(源自您的评论):
- UITableView
作为主要内容
要使键盘不可用,您可以使用名为UIScrollView
的{{1}}上的媒体资源。 (.keyboardDismissMode
派生自UITableView
,因此它继承了该属性。)
此属性的默认值为UIScrollView
。将其更改为.none
或.onDrag
。有关后两个选项之间的差异,请参阅文档。
在幕后,.interactive
在UIKit
实例和任何传入键盘之间建立连接。这允许用户通过与滚动视图交互来“滑动”键盘。
请注意,为了使此功能正常工作,您的UIScrollView
需要可滚动。要理解“可滚动”在这种情况下的含义,请see this gist。
如果您的tableView只有很少行或没有行,那么它可能无法原生滚动。为此,请设置UIScrollView
。这将确保您的用户无论表中的行数如何都可以关闭键盘。
大多数处理键盘解雇的流行应用程序也可以通过点击部分重叠的内容(在您的情况下为tableView)来解除键盘。要启用此功能,您只需在视图中安装tableView.alwaysBounceVertical = true
并在其操作方法中关闭键盘:
UITapGestureRecognizer
<小时/>
是的,您实际上可以在不使用私有API的情况下执行此操作。
的声明强>
你应该考虑一下你是否真的想要这样做。几乎在每个用例中打开键盘都应该创建一个新的编辑“上下文”,它以模块方式“阻止”其他上下文(例如class MyViewController: UIViewController {
func viewDidLoad() {
super.viewDidLoad()
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tapRecognizer)
}
}
//MARK: - Tap handling
fileprivate extension MyViewController {
@objc func handleTap() {
if searchBar.isFirstResponder {
searchBar.resignFirstResponder()
}
// Alternative
// view.endEditing(true)
}
}
// -
及其UITabBarController
提供的导航上下文)。我想有人可以指出,用户可以通过与可能存在的UITabBar
进行交互来离开编辑上下文,而UINavigationBar
通常不被键盘阻止。但是,这是整个系统中的已知交互。另一方面, Not 在显示键盘时阻止UITabBar
或UIToolbar
,不是。话虽这么说,使用下面的代码来移动键盘,但严格审查您正在创建的UX。我不是说它移动键盘永远不会有意义,但你应该真的知道你在这里做了什么。说实话,键盘浮动在标签栏上面也看起来有些不确定。
<强>代码强>
extension Sequence {
func last(where predicate: (Element) throws -> Bool) rethrows -> Element? {
return try reversed().first(where: predicate)
}
}
// Using `UIViewController` as an example. You could and actually should factor this logic out.
class MyViewController: UIViewController {
deinit {
NotificationCenter.default.removeObserver(self)
}
func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: .UIKeyboardWillHide, object: nil)
}
}
//MARK: - Keyboard handling
extension MyViewController {
private var keyboardOffset: CGFloat {
// Using a fixed value of `49` here, since that's what `UITabBar`s height usually is.
// You should probably use something like `-tabBarController?.tabBar.frame.height`.
return -49
}
private var keyboardWindowPredicate: (UIWindow) -> Bool {
return { $0.windowLevel > UIWindowLevelNormal }
}
private var keyboardWindow: UIWindow? {
return UIApplication.shared.windows.last(where: keyboardWindowPredicate)
}
@objc fileprivate func keyboardWillShow(notification: Notification) {
if let keyboardWindow = keyboardWindow {
keyboardWindow.frame.origin.y = keyboardOffset
}
}
@objc fileprivate func keyboardWillHide(notification: Notification) {
if let keyboardWindow = keyboardWindow {
keyboardWindow.frame.origin.y = 0
}
}
}
// -
<强>注意强>
请注意,如果您使用.UIKeyboardWillShow
和.UIKeyboardWillHide
通知来考虑视图中的键盘(例如,设置UIScrollView
插入内容),您还必须考虑移动键盘窗口的任何其他偏移量。
这适用于iOS 11并且已经过测试。但是,无法保证UIKit团队不会更改Windows的顺序或其他在未来版本中打破此功能的内容。同样,你没有使用任何私有API,因此AppStore评论不应该有危险,但你正在做一些你不应该对框架做的事情,并且总是会出现这种情况并在以后咬你。