当很清楚并且不同的uiview可以处理它们时,如何忽略最上面的uiview中的触摸事件
Posted
技术标签:
【中文标题】当很清楚并且不同的uiview可以处理它们时,如何忽略最上面的uiview中的触摸事件【英文标题】:how to disregard touch events in topmost uiview when it is clear and a different uiview can handle them 【发布时间】:2014-02-20 13:11:57 【问题描述】:我有一个清晰的 UIView,上面附有手势识别器。
这个清晰的 uiview 覆盖了整个超级视图,以允许从其上的任何位置调用手势。
在这个清晰的 UIView 下有不同的组件,例如表格、按钮、集合视图等。
清晰的 UIView 随时都不知道下面是什么。
我想要什么 - 如果清晰 uiview 下的视图可以处理触摸事件(或任何类型的手势) - 清晰视图应该忽略该事件 - 并且事件将传递到可以处理的底层视图它。
我试过了
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
但我不知道如何确保底层视图可以处理它。
【问题讨论】:
这个清晰视图的目的是什么? 我认为你可以使用手势识别器委托方法gestureRecognizer:shouldReceiveTouch:来做到这一点。设置一个条件,如果触摸在您想要接收的控件的矩形内,则手势将被忽略,按钮将接收触摸。 这个问题你解决了吗? 【参考方案1】:-(id)hitTest:(CGPoint)point withEvent:(UIEvent *)event
id hitView = [super hitTest:point withEvent:event];
if (hitView == self)
return nil;
else
return hitView;
将此添加到您的清晰视图中。
如果点击清晰视图意味着返回 nil。
【讨论】:
超级视图如何将事件传递给相关视图 命中测试不同于superview子视图的概念。 touch 总是从应用程序窗口开始并沿着应用程序中的所有视图移动。您的应用程序中的每个视图都将收到 hitevent 如果return nil的意思,说明这个view不需要触摸事件【参考方案2】:您可以覆盖pointInside: withEvent:
方法。该方法返回一个布尔值,指示接收器是否包含指定的点。因此,如果我们返回NO
,那么您的上层清晰视图将对触摸事件变得透明,并且它们将被传递给底层视图。
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
// Clear UIView will now respond to touch events if return NO:
return NO;
【讨论】:
【参考方案3】:为您的案例使用以下代码->
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
UIView *hitTestView = [super hitTest:point withEvent:event];
if(hitTestView!=nil)
//check for gesture
if([hitTestView.gestureRecognizers count]>0)
return hitTestView;
//if it is subclass of UIControl like UIButton etc
else if([hitTestView isKindOfClass:[UIControl class]])
return hitTestView;
//if can handle touches
else if([hitTestView respondsToSelector:@selector(touchesBegan:withEvent:)])
return hitTestView;
else
return nil;
else
return self;
在上面的代码中,如果作为 hitView 的 subView 无论如何都可以处理触摸,我们返回那个对象来处理那个触摸。如果没有这样的 hitTest 视图,那么我们返回视图本身。
【讨论】:
【参考方案4】:我使用了其中的一些建议并使用了以下解决方案:
我将手势识别器添加到层次结构中最底部的超级视图(而不是最顶部)
然后在那个班级里摆脱
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
UIView *v = [super hitTest:point withEvent:event];
// if v is nil then touch wasn't in this view or its subviews
if (v == nil)
return nil;
// in any case if the topview was hidden than return the default value
if (self.myTopView.hidden)
return v;
// if the view isn't hidden but the touch returned a control - than we can pass the touch to the control
if ([v isKindOfClass:[UIControl class]])
return v;
// decide on what threshold to decide is a touch
CGFloat threshHold = 40;
// if the touch wasn't on a control but could initiate a gesture than that view should get the touch
if (v.gestureRecognizers)
threshHold = 30;
// return v;
// check if the threshold should be bigger
if ([self someCondition])
threshHold = 100;
// threshold according to its position - this is the dynamic part
if (point.y > (self.myTopView.frame.origin.y - threshold))
return self.handleBarView;
return v;
【讨论】:
以上是关于当很清楚并且不同的uiview可以处理它们时,如何忽略最上面的uiview中的触摸事件的主要内容,如果未能解决你的问题,请参考以下文章
SQLAlchemy:如何在删除时禁用 ORM 级外键处理?
通过在它们上方移动另一个 UIView 来获取所有 UIViews