尝试根据窗口内的 CGPoint 来确定命中了什么(如果有)可访问性元素。这可能吗?可访问性元素命中测试的排序...应该返回任何可访问性元素命中(包括系统创建)。似乎必须有办法做到这一点。
4 回答
我最好的答案是:将所有可访问性元素添加到数组中。在您的 touchesEnded 方法中,枚举数组并检查是否有任何元素被触摸。一种方法是检查元素的boundingBox 是否包含CGPoint。然后你可以写一堆代码来响应那个触摸!希望这有帮助!^_^
两种可能的方法来做到这一点。第一个,您创建一个类别UIView
(新文件,类别,将其命名为“tapped”,“UIView”的子类)并将以下代码放入其中:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSLog(@"%@", self);
}
到目前为止,此代码将适用于所有UIView
s,但不适用于其自身的所有子类。所以你需要创建更多的子类(例如UIControl
,,UIWindow
等)。在那些子类中你不需要NSLog()
任何东西,只需调用:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
}
因为所有这些子类都会调用超类,它们最终会调用NSLog()
of UIView
。缺点是您必须为所有情况创建大量子类。例如,您需要UIView
for UIControl
,然后UIControl
forUIButton
等等。
.
另一种方式并不完全符合您的要求,但更容易。只需递归调用子视图。
- (void)logView:(UIView*)v index:(int)i
{
NSMutableString *str = [NSMutableString string];
for (int u = 0; u<i; u++) { [str appendString:@"| "]; }
[str appendFormat:@"<%@ %p frame:%@>", v.class, v, NSStringFromCGRect(v.frame)];
// of course you can change it to display your accessibility hint/label
printf("%s\n", [str UTF8String]);
for (UIView *vv in v.subviews) { [self logView:vv index:i+1]; }
}
你调用这个方法一次:
[self logView:self.view index:0];
…它会自动创建一个树作为输出:
<UITextField 0x6b30010 frame:{{20, 13}, {280, 31}}>
| <UITextFieldRoundedRectBackgroundView 0x6b31e00 frame:{{0, 0}, {280, 31}}>
| | <UIImageView 0x6b31fe0 frame:{{0, 0}, {0, 0}}>
| | <UIImageView 0x6b32070 frame:{{0, 0}, {0, 0}}>
| | <UIImageView 0x6b320e0 frame:{{0, 0}, {0, 0}}>
我担心为了实现你想要的,你必须基本上重新实现例如浏览器如何在 DOM 中的事件处理中执行捕获阶段:
- 从最通用的元素开始——在任何基于 UIKit 的应用程序中,这将是应用程序的
keyWindow
或(如果您的应用程序是多屏的)屏幕的最前面的窗口,您必须通过windowLevel
等等来弄清楚。 - 检查有问题的对象是否是可访问性容器,以及
- 如果是这样,递归到那个,要求适当的东西。
- 如果不是,请检查它是否是可访问性元素,并且
- 如果不是保释。
- 如果是,请检查其可访问性框架是否包含有问题的点。
- 现在,如果发生这种情况,恭喜:您已成功找到有问题的元素,因此您应该返回它。
- 如果不是这样,保释。
到目前为止,我们已经处理了可访问性元素和容器内元素的情况。
还有一种情况需要介绍,即可访问性容器,它们本身就是可访问性元素:
我们有一个容器,它没有为所讨论的点生成元素。
如果它是一个可访问性元素,检查它的框架是否包含该点,并且 - 如果是,则返回self
, - 如果不是,则保释。
我所说的保释总是意味着零回报。
现在抓住所有这些逻辑,将其转换为代码,并将其放入NSObject
.
目前,似乎没有办法使用最新的 API 来做到这一点。