我有一堆UIViews,如下图所示。红色/粉色(半透明)视图位于其他视图之上。


红色有一个UISwipeGestureRecognizer
绿色为UITapGestureRecognizer
蓝色没有识别器。




点击绿色的可见(左下)部分会触发其识别器。

点击绿色的隐藏部分不会触发其识别器(红色会阻止它)。

这就是问题所在:我希望格林触发。我怎样才能做到这一点?

实际上,视图可以是任意顺序,任意数量,并且可以是彼此的子视图,等等。但是问题是相同的:

如何可靠地找到可以处理手势(轻击或轻扫)的最上方视图?



我尝试了下面的代码。它整齐地遍历所有视图,但是由于不知道事件是滑动还是轻击的一部分而失败。因此,该方法始终返回红色视图。如果我从红色中移除了滑动识别器,则代码可以正常工作。

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView *hitView = [super hitTest:point withEvent:event];
    if (hitView == self)
    {
        if (self.hasASwipeRecognizer)
            return self;  // What if this was a tap?
        if (self.hasATapRecognizer)
            return self;
        else
            return nil;
    }
    else
         return hitView;
 }

最佳答案

将手势识别器添加到这些视图的替代方法是将手势识别器添加到父视图,并使用委托方法gestureRecognizer:shouldReceiveTouch:方法适当地处理用例。

标识特定识别器是否应该接收触摸并返回YES。例如,如果传递的手势识别器是滑动识别器,则检查触摸点是否在绿色视图内并返回YES。否则返回NO

如果有类似的手势识别器,那么我建议您保留一个参考并进行验证。

用法

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint pointInView = [touch locationInView:gestureRecognizer.view];

    if ( [gestureRecognizer isMemberOfClass:[UITapGestureRecognizer class]]
        && CGRectContainsPoint(self.blueView.frame, pointInView) ) {
        return YES;
    }

    if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]]
        && CGRectContainsPoint(self.greenView.frame, pointInView) ) {
        return YES;
    }

    return NO;
}

08-27 19:13