Tho*_*ert 13 iphone events uiview hittest
我试图拦截在我的整个应用程序中发生的任何活动(即触摸).
换句话说,我正在尝试通知我的主要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];
}
Run Code Online (Sandbox Code Playgroud)
这是我在这个视图中单次触摸的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] ---
Run Code Online (Sandbox Code Playgroud)
我怎么能在这三个通知之间做出任何区别,以便触发我想只进行一次触摸的动作?
提前致谢 !
sds*_*kes 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
}
}
Run Code Online (Sandbox Code Playgroud)
小智 8
如果这仍然是你的问题.
我找到了几个关于这个主题的例子和讨论,但正确的解决方案非常简单.
通常,在UIView或UIScrollView中调用hittest三次 - 这是遍历视图层次结构的结果.
一个非常简单,对我来说总是合适的解决方案是:
在您实现的视图中实现函数hittest
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
Run Code Online (Sandbox Code Playgroud)
对我来说 - 所有三个函数调用始终具有相同的位置 - 所以只需将位置存储在本地类中.
在.h文件中:
@interface MyScrollView : UIScrollView {
CGPoint touchLocation_;
}
@property (nonatomic, readonly) CGPoint touchLocation;
Run Code Online (Sandbox Code Playgroud)
在.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];
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案很适合我在几个项目中.
您收到的事件响应的数量取决于视图层次结构。
\n\n\n\n\n此方法通过向每个子视图发送\n pointInside:withEvent: 消息来遍历视图\n 层次结构,以确定哪个子视图\n 应接收触摸事件。如果\n pointInside:withEvent: 返回 YES,\n 则遍历子视图\xe2\x80\x99s 层次结构;\n 否则,视图层次结构的分支将被忽略。您很少需要自己调用此方法,但您可以重写它以隐藏子视图中的触摸事件。
\n\n此方法会忽略隐藏的、已禁用用户交互或 Alpha 级别小于 0.01 的视图对象。此方法在确定命中时\n 不考虑视图\xe2\x80\x99s 内容。因此,即使指定点位于该视图内容的透明部分,仍然可以返回视图。
\n\n位于接收器\xe2\x80\x99s\n 边界之外的点永远不会被报告为命中,\n 即使它们实际上位于\n 接收器\xe2\x80\x99s 子视图之一内。如果当前视图\xe2\x80\x99s\n ClipsToBounds 属性设置为 NO\n 并且受影响的子视图\n 超出视图\xe2\x80\x99s 边界,则可能会发生这种情况。
\n
来自UIView 类参考。
\n\n简而言之,如果您触摸的视图具有三个子视图,并且这些视图可见并且在其父视图和触摸区域的范围内,您将收到三个命中测试响应。
\n