为keyboardWillShowNotification设置UIScrollView的contentInset无法正常工作

问题描述 投票:0回答:1

我有一个具有以下结构的ViewController((x)表示级别):

UIViewController    (1)
  - NavigationBar   (2)
  - UIScrollView    (2)
    - UIView        (3)
      - UITextField (4)
      - UITextField (4)
      - UITextField (4)
      - UITextField (4)
      - UIButton    (4)
  • 级别4的所有元素彼此垂直约束,间距为16。
  • 级别4的第一个和最后一个元素被限制在UIView的(3)顶部和底部。
  • UIView(3)的顶部和底部被限制在UIScrollView(2)。
  • [UIScrollView(2)被限制在NavigationBar的底部(2)和超级视图的底部(1
  • (当然也有必要的水平约束!)

UIView(3)具有以下约束:

  • 所有子视图的领先约束为0。
  • 对所有子视图的跟踪约束为0。
  • UIButton的24个底部空格(应添加some额外的间距)
  • 顶部的24个空格到最顶部的UITextField(顶部的间距)
  • 0到superView的顶部空间(UIScrollView)
  • 到superView(UIScrollView)的0的底部空间
  • '等于宽度-减去32'到NavigationBar(因此-固定宽度)

在viewController的viewDidLoad中,我称之为:

registerForKeyboardWillShowNotification(self.scrollView)
registerForKeyboardWillHideNotification(self.scrollView)

registerForKeyboard...ShowNotificationUIViewController的扩展名:

extension UIViewController
{
    /// Act when keyboard is shown, by adding contentInsets to the scrollView.
    func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
    {
        _ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification,
                                                   object: nil, queue: nil)
        { notification in
            let userInfo      = notification.userInfo!
            let keyboardSize  = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
            let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
                                             left: scrollView.contentInset.left,
                                             bottom: keyboardSize.height,
                                             right: scrollView.contentInset.right)

            scrollView.contentInset = contentInsets
            block?(keyboardSize)
        }
    }

    /// Act when keyboard is hidden, by removing contentInsets from the scrollView.
    func registerForKeyboardWillHideNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
    {
        _ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification,
                                                   object: nil, queue: nil)
        { notification in
            let userInfo = notification.userInfo!
            let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
            let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
                                             left: scrollView.contentInset.left,
                                             bottom: 0,
                                             right: scrollView.contentInset.right)

            scrollView.contentInset = contentInsets
            block?(keyboardSize)
        }
    }
}

但是,当键盘显示时,它没有插入scrollView(足够大)。我调试了,情况就是这样:

  • 常规键盘:height = 216
  • 带有建议栏的普通键盘:height = 260
  • 带有建议栏的iPhone X键盘:height = 291

尽管建议栏可能是我的问题,但不是。

registerForKeyboardWillShowNotification中,我将bottom: keyboardSize.height更改为bottom: keyboardSize.height + 30,得到的结果完全相同(我看到按钮的相同部分部分隐藏在键盘后面)。一旦添加50或更多,它似乎最终会产生很小的变化。

  • 而不是我尝试了keyboardWillShowNotification,而不是keyboardDidShowNotification,这没有什么区别。
  • 而不是我尝试了keyboardFrameEndUserInfoKey,而不是keyboardFrameBeginUserInfoKey,这没有什么区别。

我在这里想念什么?

ios swift uiscrollview uikeyboard
1个回答
0
投票

不幸的是,我无法解决这个问题,我不确定为什么它不能按预期工作。

但是,我通过使用UIScrollView内的UIStackView得到了预期的行为。我以this article作为参考。


UI布局

  • UIViewController(1)
    • NavigationBar(2)
    • UIScrollView(2)
    • UIStackView(3)
      • UITextField(4)
      • UITextField(4)
      • UITextField(4)
      • UITextField(4)
      • UIButton(4)

[UIScrollView

  • ScrollView的leadingtrailing16限制到超级视图。
  • ScrollView的top被导航栏底部的0约束。
  • ScrollView的bottom被超级视图底部的0约束。

[UIStackView

  • StackView的leadingtrailing0约束到scrollView。
  • StackView具有与scrollView相同的宽度。
  • StackView的topbottom24限制到scrollView,以获取所需的NavigationBar间距,以及按钮和键盘之间的间距。
  • 将StackView设置为axis=verticalalignment=filldistribution=fillspacing=24

The NavigationBar

NavigationBar是一个自定义类,它从其内容派生其高度。它没有设置高度限制,但是占位符高度为100。NavigationBar将填满整个屏幕。这可以通过以下方法解决:删除占位符的高度,并以低优先级(在这种情况下,优先级为1)添加any高度约束。


现在可以使用应用键盘插入的初始代码。

/// Act when keyboard is shown, by adding contentInsets to the scrollView.
func registerForKeyboardWillShowNotification(_ scrollView: UIScrollView, usingBlock block: ((CGSize?) -> Void)? = nil)
{
    _ = NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification,
                                               object: nil, queue: nil)
    { notification in
        let userInfo      = notification.userInfo!
        let keyboardSize  = (userInfo[UIResponder.keyboardFrameEndUserInfoKey]! as AnyObject).cgRectValue.size
        let contentInsets = UIEdgeInsets(top: scrollView.contentInset.top,
                                         left: scrollView.contentInset.left,
                                         bottom: keyboardSize.height,
                                         right: scrollView.contentInset.right)

        scrollView.contentInset = contentInsets
        block?(keyboardSize)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.