仅使用UIKeyboardWillChangeFrameNotification通知

14
考虑键盘新的QuickType部分。
只使用UIKeyboardWillChangeFrameNotification通知,而简单地“不用管”早期的UIKeyboardWillShowNotification和UIKeyboardWillHideNotification ,这是完全可行的吗?
测试似乎表明,仅使用keyboardFrameDidChange功能就可以完美地工作,但我们可能会错过一些东西?
顺便说一下,这是如何使用UIKeyboardWillChangeFrameNotification的示例: https://dev59.com/9l8d5IYBdhLWcg3w-mXX#26226732
1个回答

36

2021-05-17更新,适用于Swift 5

这是完全可以实现的,并且可以将您的代码压缩近一半。以下示例使用自动布局来完成大部分重要工作。

NotificationCenter.default.addObserver(
    forName: UIResponder.keyboardWillChangeFrameNotification,
    object: nil,
    queue: nil
) { (notification) in
    guard let userInfo = notification.userInfo,
          let frameEnd = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
          let curveRaw = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int,
          let curve = UIView.AnimationCurve(rawValue: curveRaw),
          let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval
    else { return }

    // Convert the frame rects you're interested in to a common coordinate space
    let keyboardRect = self.view.convert(frameEnd, from: nil)
    let formContainerRect = self.view.convert(self.formContainerView.frame, from: nil)

    // Calculate their intersection and adjust your constraints accordingly
    let intersection = keyboardRect.intersection(formContainerRect)
    if !intersection.isNull {
        // Some overlap; adjust the bottom of your views (what you do here will vary)
        self.formContainerBottomConstraint?.constant = intersection.size.height
    } else {
        // No overlap; reset your views to its default position
        self.formContainerBottomConstraint?.constant = 0
    }

    let animator = UIViewPropertyAnimator.init(duration: duration, curve: curve) {
        self.view.layoutIfNeeded()
    }
    animator.startAnimation()
}

self.formContainerBottomConstraint 是将(想象中的)表单底部绑定到视图底部的一个 NSLayoutConstraint。这段代码会在键盘出现时将表单向上移动,在键盘消失时将其向下移动。

iOS < 8 版本可以通过结合使用 UIKeyboardWillShowNotificationUIKeyboardWillHideNotification 实现这一功能。但是,iOS 8 引入了 QuickType 区域,用户可以折叠或展开它。使用该解决方案非常灵活,能够让你的应用响应操作系统引发的任何键盘变化。


有没有办法控制滚动?在iPhone 6上,当用户在最顶部的文本字段上编辑时,我不需要字段滚动,但当他们编辑底部文本字段时,它应该滚动以腾出空间。 - Todd Hoff
使用 UIViewAnimationOptions(UInt(curve)) 的方法正确吗?文档中说 curve 是一个 UIViewAnimationCurve,但是根据定义,它似乎与 UIViewAnimationOptions 的值不匹配。更糟糕的是,在实践中,这个通知返回的 curve 值是 7 -- 一个私有/未定义的值,所以简单的 switch 语句不能转换它们... - Dave Peck
1
有没有Objective-C的解决方案? - new2ios
@ToddHoff 在事件处理程序中,您需要检查哪个文本字段是当前的第一响应者:self.bottomTextField.isFirstResponder - adamrothman
1
@DavePeck 你说得对,根据我的研究,目前没有一个伟大的/被苹果推荐的方法来在两者之间进行转换。我会更新答案,并提供我认为目前最好的选项(并且适用于Swift 2)。 - adamrothman
我发现自己需要为一个新项目再次这样做,觉得现在是更新Swift 4答案的好时机。祝你编程愉快! - adamrothman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接