ios - 将键盘移至 Tab ViewController TabBar 上方

标签 ios swift uikeyboard

是否可以向上移动键盘使其不覆盖 UITableViewController TabBar?

最佳答案

在评论中获得更多上下文后更新

如果您主要关心的是让用户关闭键盘,那么平台上通常应用一些众所周知的模式:

关于 UI 的假设(源自您的评论):
- UITableView 作为主要内容

要使键盘可关闭,您可以使用 UIScrollView 上名为 .keyboardDismissMode 的属性。 (UITableView 派生自UIScrollView,因此继承了该属性。)

此属性的默认值为 .none。将其更改为 .onDrag.interactive。有关后两个选项之间的差异,请参阅文档。 在幕后,UIKitUIScrollView 实例和任何传入的键盘之间建立连接。这允许用户通过与 ScrollView 交互来“滑动”键盘。

请注意,为了使此功能起作用,您的 UIScrollView 需要可滚动。要了解“可滚动”在这种情况下的含义,请 see this gist .

如果您的 tableView 的行很少或没有行,则它可能无法原生滚动。为此,请设置 tableView.alwaysBounceVertical = true。这将确保无论表格中的行数如何,您的用户都可以关闭键盘。

大多数处理键盘关闭的流行应用程序也可以通过点击部分重叠的内容(在您的例子中是 tableView)来关闭键盘。要启用此功能,您只需在 View 上安装 UITapGestureRecognizer 并在其操作方法中关闭键盘:

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)
  }
}
// -


旧答案

是的,您实际上可以在不使用私有(private) API 的情况下执行此操作。

免责声明

你真的应该考虑一下你是否真的想这样做。在几乎每个用例中打开键盘都应该创建一个新的编辑“上下文”,它模态地“阻止”其他上下文(例如 UITabBarController 及其 UITabBar 提供的导航上下文).我想有人可能会指出,用户可以通过与可能存在的 UINavigationBar 交互来离开编辑上下文,这通常不会被键盘阻止。但是,这是整个系统的已知交互。 不是在另一方面显示键盘时阻止 UITabBarUIToolbar不是。也就是说,使用下面的代码将键盘向上移动,但批判性地审查您正在创建的用户体验。我并不是说向上移动键盘永远没有意义,但您真的应该知道自己在做什么。老实说,键盘悬浮在标签栏上方,这看起来也有点不靠谱。

代码

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 通知来说明 View 中的键盘(设置 UIScrollView 插入,例如),您还必须考虑移动键盘窗口的任何额外偏移量。

这在 iOS 11 上有效并经过测试。但是,不能保证 UIKit 团队不会在未来的版本中更改窗口的顺序或其他破坏此功能的东西。同样,您没有使用任何私有(private) API,因此 AppStore 审查应该不会有危险,但是您正在做一些您不应该使用框架做的事情,而且这总是可以解决的然后咬你。

关于ios - 将键盘移至 Tab ViewController TabBar 上方,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47229511/

相关文章:

swift - 编程约束未按预期工作

ios - UITableView reloadData() 不刷新显示的单元格

iOS 13 Xcode 如何删除 UIKeyboard 上的 QuickType(自动完成/自动建议)

objective-c - "Current language: auto; currently objective-c"是什么意思?

ipad - UISwipeGestureRecognizer、UITapGestureRecognizer 和 MPMoviePlayerController 的问题 :-(

swift - 为什么我的搜索栏仅在我使用时才停留在顶部?

ios - 在 UIScrollView 中滚动时禁用键盘

ios - iOS 8 通知的 UIKeyboard 建议高度?

ios - AVPlayer HLS 不适用于物理设备

ios - iOS 中的多个主题模式处理