当视图控制器内部有滚动视图时处理键盘事件

Posted

技术标签:

【中文标题】当视图控制器内部有滚动视图时处理键盘事件【英文标题】:Handling keyboard events when view controller has a scrollview inside 【发布时间】:2020-04-02 17:42:38 【问题描述】:

在我的项目中,有一个视图控制器嵌入在标签栏控制器中。这个视图控制器有一个显示抽屉(滑入式视图)的按钮。我为此使用了this 第三方库。从现在开始,我将它称为面板视图控制器。

这个面板视图控制器是一个简单的视图控制器,里面有一个滚动视图。滚动视图中有一个堆栈视图。所有其他子视图(绿色和橙色视图)都通过堆栈视图布局。

橙色视图的底部有一个文本字段。我编写了以下代码来处理键盘事件以将文本字段移动到键盘上方并向下移动。

@objc private func didReceiveKeyboardNotification(_ notification: Notification) 
    if
        let userInfo = notification.userInfo,
        let endValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue,
        let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double,
        let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt 

        // Transform the keyboard's frame into our view's coordinate system
        let endRect = view.convert(endValue.cgRectValue, from: view.window)

        // Find out how much the keyboard overlaps the scroll view
        // We can do this because our scroll view's frame is already in our view's coordinate system
        let keyboardOverlap = scrollView.frame.maxY - endRect.origin.y

        // Set the scroll view's content inset to avoid the keyboard
        // Don't forget the scroll indicator too!
        scrollView.contentInset.bottom = keyboardOverlap
        scrollView.verticalScrollIndicatorInsets.bottom = keyboardOverlap

        UIView.animate(withDuration: duration, delay: 0, options: UIView.AnimationOptions(rawValue: curve), animations: 
            self.view.layoutIfNeeded()
        , completion: nil)
    

键盘关闭后,视图应向下移回初始位置。问题是滚动视图没有重置到原始位置。如您所见,文本字段最终低于初始位置。

我不知道这里有什么问题。

Demo project

【问题讨论】:

【参考方案1】:

didReceiveKeyboardNotification 方法中的问题。您使用相同的方法来处理显示/隐藏键盘,并且在这两种情况下,您都使用scrollView.contentInset.bottom = keyboardOverlap,因此在键盘隐藏后您的插入将设置为 0。这是更正确的方法:

        if notification.name == UIResponder.keyboardWillHideNotification 
            let inset = tabBarController?.tabBar.frame.size.height as! CGFloat //Tabbar height
            scrollView.contentInset.bottom = inset
            scrollView.verticalScrollIndicatorInsets.bottom = inset
        

        if notification.name == UIResponder.keyboardWillShowNotification 
            scrollView.contentInset.bottom = keyboardOverlap
            scrollView.verticalScrollIndicatorInsets.bottom = keyboardOverlap
        

【讨论】:

【参考方案2】:

试试IQKeyboardManager。我有一个类似的问题,这解决了它没有任何代码,它只是工作。

【讨论】:

以上是关于当视图控制器内部有滚动视图时处理键盘事件的主要内容,如果未能解决你的问题,请参考以下文章

iphone弹出键盘时取消滚动动画

嵌套的 UIScrollViews 和事件路由

仅当键盘覆盖视图时如何更改 UITableView 内容插图?

UITextField 是不是消耗触摸事件?

键盘显示时更改自动布局常量

Swift:当键盘显示时向上滚动视图