我试图拦截在整个应用程序中发生的任何活动(即触摸)。
换句话说,我正在尝试通知我的主UIView中发生的任何触摸事件,其中包含我的其余控件。 为此,我认为UIView的方法-hitTest:withEvent:是一个很好的解决方案。
然而,当我在调用[super hitTest:... withEvent:...]之前NSLog进入这个重写方法时,我看到它被调用3次,因为我做了任何触摸,我看不出任何差别我每次打电话都会收到这个事件。
以下是如何在我的应用程序的主视图中实现该方法:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
NSLog(@"hitTest:withEvent called :");
NSLog(@"Event: %@", event);
NSLog(@"Point: %@", NSStringFromCGPoint(point));
NSLog(@"Event Type: %d", event.type);
NSLog(@"Event SubType: %d", event.subtype);
NSLog(@"---");
return [super hitTest:point withEvent:event];
}
以下是我在这个视图中单次触摸的NSLog:
2010-11-29 14:09:26.892 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.892 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37935.2 touches: {(
)}
2010-11-29 14:09:26.892 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.892 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.892 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.893 Application[68818:207] ---
2010-11-29 14:09:26.893 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.893 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37935.2 touches: {(
)}
2010-11-29 14:09:26.893 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.893 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.893 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.893 Application[68818:207] ---
2010-11-29 14:09:26.893 Application[68818:207] hitTest:withEvent called :
2010-11-29 14:09:26.894 Application[68818:207] Event: <UITouchesEvent: 0x5716d60> timestamp: 37944.9 touches: {(
)}
2010-11-29 14:09:26.894 Application[68818:207] Point: {173, 498}
2010-11-29 14:09:26.894 Application[68818:207] Event Type: 0
2010-11-29 14:09:26.894 Application[68818:207] Event SubType: 0
2010-11-29 14:09:26.894 Application[68818:207] ---
我如何才能触发这三个通知之间的任何差异,以便触发我想只进行一次触摸的动作?
提前致谢!
答案 0 :(得分:10)
确实有3次调用hitTest。目前尚不清楚为什么,但我们可以通过事件的时间戳来推测,前两个调用与完成前一个手势有关 - 这些时间戳总是非常接近于前一次触摸发生时,并且距离当前时间。
这就是我如何确定要处理的hitTest:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSTimeInterval system = [[NSProcessInfo processInfo] systemUptime];
if (system - event.timestamp > 0.1) {
// not the event we were interested in
} else {
// use this call
}
}
答案 1 :(得分:8)
如果这仍然是您的问题。
我找到了几个关于这个主题的例子和讨论,但正确的解决方案非常简单。
一般来说,在UIView或UIScrollView中调用hittest三次 - 这是遍历视图层次结构的结果。
一个非常简单的,对我来说总是合适的解决方案是:
在您实施的视图中实现功能hittest
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
对我来说 - 所有三个函数调用都始终保持相同的位置 - 所以只需将位置存储在本地类中。
<。>文件中的:
@interface MyScrollView : UIScrollView {
CGPoint touchLocation_;
}
@property (nonatomic, readonly) CGPoint touchLocation;
.m文件中的
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
return [super hitTest:point withEvent:event];
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
// The point check you need
if(point.y != self.touchLocation.y){
touchLocation_ = point;
// The function call you need - just called once.
}
return [super pointInside:point withEvent:event];
}
这个解决方案很适合我在几个项目中。
答案 2 :(得分:2)
您收到的事件响应数取决于视图层次结构。
此方法遍历视图 层次结构发送 pointInside:withEvent:发送给每个人的消息 子视图确定哪个子视图 应该收到触摸事件。如果 pointInside:withEvent:返回YES, 然后子视图的层次结构是 走过;否则,它的分支 视图层次结构被忽略。您 很少需要调用此方法 你自己,但你可以覆盖它 隐藏子视图中的触摸事件。
此方法忽略视图对象 隐藏,已禁用用户 交互,或具有alpha级别 小于0.01。这种方法没有 将视图的内容考虑在内 在确定命中时。因此,一个观点 即使是,仍然可以返回 指定的点是透明的 该视图内容的一部分。
位于接收者之外的点 边界从未被报告为命中, 即使他们实际上是在一个人之内 接收者的子视图。这个可以 如果当前视图出现 clipsToBounds属性设置为NO 受影响的子视图延伸 超出视野范围。
简而言之,如果您触摸的视图有三个子视图,并且这些视图可见并且在其超视图和触摸区域的范围内,您将收到三个命中测试响应。
答案 3 :(得分:0)
这个问题已经问了多年了,但我想回答:
系统多次调用hitTest和pointInside来固定位置,并且每次调用堆栈都不相同时,请从Apple咨询the official reply。