敲击键盘时触发 hotTest

Posted

技术标签:

【中文标题】敲击键盘时触发 hotTest【英文标题】:hitTest fires when UIKeyboard is tapped 【发布时间】:2011-11-09 23:05:44 【问题描述】:

我正在尝试修复涉及 UIView hitTest:withEvent: 在 UIKeyboard 上进行触摸时在我的视图上调用的错误,但仅在应用程序已在后台运行后调用。

它发生在我的应用程序中,具有复杂的视图层次结构,因此我在一个只有 2 个视图的应用程序中重现了它:

1 UIView 768x1024(全屏) 1 UITextView 200x200 在全屏视图的上半部分

行为如下:

点击文本视图会导致全屏视图的 hitTest 方法触发,文本字段成为第一响应者,然后键盘按预期显示。敲击键盘按键效果很好。 现在关闭键盘。 将应用程序发送到后台。 然后恢复应用。 再次使 textview 成为第一响应者。问题来了,现在当点击键盘上的键时,全屏视图的 hitTest 方法正在触发。

我在 ios 5 iPad 2 上看到了这一点。但仅在设备上,从不在模拟器中。知道为什么 hitTesting 会以这种方式搞砸吗?谢谢。

【问题讨论】:

【参考方案1】:

上面描述的问题似乎是由于键盘的 UIWindow 卡在了错误的状态。确保键盘窗口的 hidden 属性设置为 YES(即使它已经是 YES)为我解决了这个问题。这可以在您的 UIApplicationDelegate 类中完成:

- (void)applicationWillEnterForeground:(UIApplication *)application 
    // The keyboard sometimes disables interaction when the app enters the 
    // background due to an iOS bug. This brings it back to normal.
    for (UIWindow *testWindow in [UIApplication sharedApplication].windows) 
        if (!testWindow.opaque && [NSStringFromClass(testWindow.class) hasPrefix:@"UIText"]) 
            BOOL wasHidden = testWindow.hidden;
            testWindow.hidden = YES;

            if (!wasHidden) 
                testWindow.hidden = NO;
            

            break;
        
    

键盘窗口的类名,至少在带有标准美式键盘的 iOS 5 中,是 UITextEffectsWindow。像往常一样,依赖未记录的类名不是一个好主意,但对于特定于操作系统的错误,它适用于我的目的。可以有任意数量的窗口,包括根应用程序窗口、键盘、警报以及您的应用程序或其他框架添加的其他窗口,所以不要太具体。

【讨论】:

【参考方案2】:

这里有同样的问题。只有当我回家并返回应用程序时才会发生这种情况。 在第一次新运行时不会发生。

而且和iOS5也有关系。

【讨论】:

感谢您的确认,我将向 Apple 提交错误报告。如果其他人也可以打开重复的错误,我将不胜感激。 当然。只是为了分享更多发现: * iOS 5.0.1 上的相同问题 * 模拟器上不会出现 * iPhone 和 iPod 设备上也会出现同样的问题 * 在 iOS 5 之前的 SDK 上构建的版本中不会出现 就我而言,我通过使用另一个委托而不是 hitTest 解决了这个问题。这个成功了: - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;是的,它是一个被 tableview 调用的滚动视图委托。 今天早上我遇到了这个错误:|感谢您确保错误。【参考方案3】:

我遇到了同样的问题,我的解决方法是听 UIKeyboardDidShowNotification 和 UIKeyboardDidHideNotification,使用 UIKeyboardFrameEndUserInfoKey 计算键盘高度,然后在我的 hitTest:withEvent: 方法中,我会看到点击是在键盘“区域”还是不是。

【讨论】:

是的,我也必须做这样的事情,但这绝对不理想。【参考方案4】:

只是为了扩展@enzo-tran 的答案,这就是我最终要做的事情:我在我的 UIView 子类中添加了一个 keyboardRect 属性,注册了UIKeyboardDidShowNotificationUIKeyboardDidHideNotification,并添加了:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
  if (CGRectContainsPoint([self keyboardRect], point)) 
    // Ignore      
   else 
    ...
  


- (void)keyboardDidShow:(NSNotification *)notif 
    CGRect keyboardRect;

    [[[notif userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
    keyboardRect = [self convertRect:keyboardRect fromView:nil];

    [self setKeyboardRect:keyboardRect];


- (void)keyboardDidHide:(NSNotification *)notif 
    [self setKeyboardRect:CGRectZero];

【讨论】:

以上是关于敲击键盘时触发 hotTest的主要内容,如果未能解决你的问题,请参考以下文章

jquery键盘事件总结

jquery键盘事件总结

回车事件如何触发不同的click

Qt:键盘焦点

事件冒泡 事件捕获 事件委托

DOM 事件深入浅出