【问题标题】:Move UIToolbar above keyboard when undocked取消停靠时将 UIToolbar 移动到键盘上方
【发布时间】:2015-05-13 14:09:02
【问题描述】:

我有一个位于屏幕底部的UIToolbar。当用户点击工具栏中的UITextField 时,键盘出现,我检测键盘大小并通过更改其自动布局约束常量来向上移动工具栏。 (它的超级视图有一个底部间距约束。)这很好,直到用户在 iPad 上取消停靠(或拆分)键盘。此时工具栏的位置不正确。我注意到在 Messages 应用程序中,工具栏始终位于键盘上方,即使用户松开键盘也是如此,并且当用户重新定位键盘时,它始终完美地位于键盘上方。在做了一些研究之后,it was suggested 通过监听UIKeyboardWillChangeFrameNotification 并检查UIKeyboardFrameEndUserInfoKey 来处理这个问题。但是,该值可能不存在,因此我不确定在这种情况下该怎么做。

我的问题是,收听键盘框架更改通知和更新自动布局约束的正确方法是,还是有其他方法可以采取(inputAccessoryView 用于突然想到的文本字段)?如果是这样,如何检测和处理各种场景(隐藏、出现、更新框架、取消停靠、重新定位)以确保它始终精确定位在键盘上方或如果没有键盘(或有硬件键盘)在底部使用)?

请参阅下文,了解我当前如何处理 UIKeyboardWillChangeFrameNotification 处理程序(Obj-C + 伪代码的混合)中的键盘出现/消失/帧更改。

这样做的问题是它在取消停靠/拆分、取消停靠时重新定位以及使用硬件键盘时错误地定位工具栏。我还发现在键盘未停靠时展开/折叠 QuickType 不会触发 UIKeyboardWillChangeFrameNotification(停靠时会触发)。

keyboardFrameWillChange {
    CGSize keyboardBeginSize = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    CGSize keyboardEndSize = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    CGFloat newOffset = 0;
    CGFloat toolbarPositionOffset = self.toolbarBottomConstraint.constant;

    //get collection view's contentInset and contentOffset

    //keyboard is appearing or disappearing or device is rotating with keyboard up
    if keyboardEndSize.height == keyboardBeginSize.height {
        if toolbarPositionOffset > 0 { //if dismissing
            newOffset = keyboardEndSize.height;
            toolbarPositionOffset -= newOffset;
            //update content inset and offset
        } else { //else appearing
            newOffset = keyboardEndSize += newOffset;
            toolbarPositionOffset += newOffset;
            //update content inset and offset
        }
    }
    //keyboard height increasing (expanding QuickType)
    else if keyboardEndSize.height > keyboardBeginSize.height {
        newOffset = keyboardEndSize.height - keyboardBeginSize.height;
        toolbarPositionOffset += newOffset;
        //update content inset and offset
    }
    //else keyboard height decreasing (collapsing QuickType)
    else {
        newOffset = keyboardBeginSize.height - keyboardEndSize.height;
        toolbarPositionOffset -= newOffset;
        //update content inset and offset
    }

    self.toolbarBottomConstraint.constant = toolbarPositionOffset;
    //set new contentInset and offset

    [self.toolbar layoutIfNeeded];
}

【问题讨论】:

  • 只需设置textField.inputAccessoryView=toolbar; 并注释掉您编写的所有代码。
  • @iphonic 这会导致崩溃:child view controller <UICompatibilityInputViewController> should have parent view controller <ViewController> but requested parent is <UIInputWindowController>
  • 它工作正常,你必须做这样的事情stackoverflow.com/a/25882277/790842,所以崩溃了。
  • @iphonic 我无法将它从超级视图中删除,它需要在键盘不可见时可见。如果我尝试将其设置为keyboardWillShow 中的inputAccessoryView,它根本不会出现。
  • 是的,我明白这一点。在这种情况下,您需要收听键盘通知。

标签: ios keyboard uitoolbar


【解决方案1】:

我找到了解决我遇到的问题的解决方案,尽管它没有提供我想要的确切最终结果。具体来说,不要尝试在取消停靠/拆分时将工具栏移动到键盘上方,在这种情况下,您可以将其固定到底部,并且仅在停靠时将其放置在键盘上方。这也解决了我在使用硬件键盘时遇到的问题。

监听UIKeyboardWillShowNotification 并将工具栏的约束常量设置为等于UIKeyboardFrameEndUserInfoKey 的值。

监听UIKeyboardWillHideNotification并将工具栏的约束常量设置为等于0。

不要听UIKeyboardWillChangeFrameNotification 或任何其他键盘通知。

通过这样做,这些通知将在键盘出现或隐藏时按照您的预期发送。但神奇的是(不是很明显我可能会添加),UIKeyboardWillShowNotification 将在键盘框架发生变化时被调用(用户展开/折叠 QuickType)。当用户松开键盘时,UIKeyboardWillShowNotification 被触发,然后UIKeyboardWillHideNotification 被立即触发。

这是在 iOS 8.4 上测试的,我可以想象这可能会因操作系统版本而异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-16
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    相关资源
    最近更新 更多