我最近遇到了一个问题,我有一个需要可滑动的超级视图和一个也需要可滑动的子视图。交互作用是,如果滑动发生在其范围内,则子视图应该是唯一一个被滑动的视图。如果滑动发生在子视图之外,则父视图应处理滑动。
我找不到任何解决这个确切问题的答案,最终想出了一个 hacky 解决方案,如果它可以帮助其他人,我想我会发布。
编辑:现在将更好的解决方案标记为正确答案。
将标题从“忽略触摸事件...”更改为“忽略手势...”
我最近遇到了一个问题,我有一个需要可滑动的超级视图和一个也需要可滑动的子视图。交互作用是,如果滑动发生在其范围内,则子视图应该是唯一一个被滑动的视图。如果滑动发生在子视图之外,则父视图应处理滑动。
我找不到任何解决这个确切问题的答案,最终想出了一个 hacky 解决方案,如果它可以帮助其他人,我想我会发布。
编辑:现在将更好的解决方案标记为正确答案。
将标题从“忽略触摸事件...”更改为“忽略手势...”
如果您正在寻找更好的解决方案,您可以使用gestureRecognizer:shouldReceiveTouch:委托方法来忽略父视图识别器的触摸。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch{
UIView* swipeableSubview = ...; //set to the subview that can be swiped
CGPoint locationInSubview = [touch locationInView:swipeableSubview];
BOOL touchIsInSubview = [swipeableSubview pointInside:locationInSubview withEvent:nil];
return !touchIsInSubview;
}
这将确保父级仅在滑动未在可滑动子视图上开始时接收滑动。
基本前提是捕捉触摸发生的时间,如果触摸发生在一组视图中,则删除手势。然后在手势识别器处理手势后重新添加手势。
@interface TouchIgnorer : UIView
@property (nonatomic) NSMutableSet * ignoreOnViews;
@property (nonatomic) NSMutableSet * gesturesToIgnore;
@end
@implementation TouchIgnorer
- (id) init
{
self = [super init];
if (self)
{
_ignoreOnViews = [[NSMutableSet alloc] init];
_gesturesToIgnore = [[NSMutableSet alloc] init];
}
return self;
}
- (BOOL) pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
CGPoint relativePt;
for (UIView * view in _ignoreOnViews)
{
relativePt = [view convertPoint:point toView:view];
if (!view.isHidden && CGRectContainsPoint(view.frame, relativePt))
{
for (UIGestureRecognizer * gesture in _gesturesToIgnore)
{
[self removeGestureRecognizer:gesture];
}
[self performSelector:@selector(rebindGestures) withObject:self afterDelay:0];
break;
}
}
return [super pointInside:point withEvent:event];
}
- (void) rebindGestures
{
for (UIGestureRecognizer * gesture in _gesturesToIgnore)
{
[self addGestureRecognizer:gesture];
}
}
@end