iPad:检测外部键盘

7
我的应用程序使用 UIAccessoryView 来提供额外的键盘功能(例如向前/向后选项卡和箭头键)以供虚拟键盘使用,但这会导致在存在物理键盘时(附件显示在屏幕底部)触发 UIKeyboardDidShowNotification 。

我想在处理 UIKeyboardWillShowNotification 时检查是否连接了物理键盘,以防止辅助视图出现并防止我的自定义视图向上滚动(为不存在的虚拟键盘腾出空间)。

我尝试检查 UIKeyboardFrameEndUserInfoKey 键,但它返回虚拟键盘的实际大小,尽管没有任何内容被显示。

有没有办法检测物理键盘的存在以防止这种不必要的行为呢?


嗯,情况变得更加复杂了。

我尝试通过从触发键盘的 Responder 对象的 inputAccessoryView 属性返回 nil 来禁用输入辅助视图。当存在物理键盘时,这将抑制 UIKeyboardWillShowNotificationUIKeyboardDidShowNotification,但在没有这样的键盘时保留这些通知。到目前为止都很好。

然后我尝试在接收到 UIKeyboardWillShowNotification 后重新启用 inputAccessoryView。这仅在需要虚拟键盘时才会触发,因此它应该允许我在这些情况下重新引入附件视图。或者至少我是这么想的。

不幸的是,似乎操作系统在 UIKeyboardWillShowNotification 之后不会检查 inputAccessoryView,因此当需要显示附件视图时,它无法显示 :o(

这让我有两个选择:

  • 包括输入辅助视图,为虚拟键盘用户提供额外的功能,但失去检测物理键盘的能力,因此不支持物理设备;或者
  • 完全排除输入辅助视图,防止大多数用户访问额外的键,但允许应用程序与物理键盘配合使用。

这不是一个很好的选择,所以我仍然希望看看是否有其他人解决了这个问题!


这听起来很奇怪。如果 UIKeyboardFrameEndUserInfoKey 没有显示键盘在屏幕上真正的显示框架,那么它就没什么用了。我会在 Apple 的 bugreporter 上报告这个问题。 - GorillaPatch
错误报告已提交,我会看看他们说什么并在这里回复。 - StuartW
@GorillaPatch 在库比蒂诺的小伙子们没有回应:( 所以在问题修复之前,我不得不取消该应用程序对物理键盘的支持。 - StuartW
报告一个错误就像献祭一只鸡一样——它可能有帮助,但不一定需要。我还会将其发布到苹果的iPhone开发者论坛和openradar上。 - GorillaPatch
2个回答

8

(此答案是由Sean Heber在Apple论坛上提出的)

当您收到UIKeyboardDidShowNotification时,不要使用UIKeyboardFrameEndUserInfoKey给出的框架,而是简单地测试视图的附加视图的位置并使用它。 我所做的就是检查附加视图的框架是什么,并将其转换为我的自己视图的坐标空间。 然后我可以轻松使用该框架来决定要做什么。

注意:当使用蓝牙键盘的弹出按钮显示/隐藏屏幕键盘时,似乎UIKit会再次发送UIKeyboardDidShowNotification,但不会发送UIKeyboardWillHideNotification。 这也是一个令人困惑的不一致性,但以上解决方法仍然有效,因为系统将在滑动屏幕键盘时更改inputAccessoryView的框架,因此您仍然可以相应地调整事物。


谢谢,很有效。要计算在视图中的绝对矩形(absolute rect),您可以使用 **CGRect absoluteFrame = [self convertRect:accessoryView.frame toView:nil];**。请注意,iOS 8会考虑屏幕方向,而< iOS 7则不会,所以在iOS 7上需要在交换 origin.x/y 之前进行处理。 - auco

2
如果您检查UIKeyboardFrameEndUserInfoKey中的框架,您会发现当外部键盘连接时它偏移键盘的高度(基本上是“出现”,但从不出现在屏幕底部以上),所以您可以将其转换为本地坐标空间并与视图的边界相交,以找到键盘的可见高度。
- (void)keyboardWillShow:(NSNotification *)notification {

    UIView *view = [self view];
    CGRect bounds = [view bounds];
    CGRect keyboardFrame = [[notification userInfo][UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect convertedKeyboardFrame = [view convertRect:keyboardFrame fromView:nil];
    CGRect intersection = CGRectIntersection(convertedKeyboardFrame, bounds);

    // intersection.size.height == 0 with external keyboards
}

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