UIGestureRecognizer subView识别器问题

时间:2011-05-19 14:54:02

标签: ios subview uigesturerecognizer

标题很难。 主要案例是这样的

UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(-200,-200,400,400)];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[subView addGestureRecognizer:tapGesture];
[superView addSubView:subView];

好的,你会发现当点击(0,0,200,200)中的区域时点击手势将生效,如果点击该点(-150,-150),点击手势将不会生效。

我不知道superView外部的点击是否会导致此问题。

任何人都知道如何解决这个问题?

2 个答案:

答案 0 :(得分:11)

要允许位于超级视图外部的子视图响应触摸,请覆盖超级视图的hitTest:withEvent:

Documentation on Event Delivery

  

触摸事件。窗口对象使用命中测试和响应者链来查找接收触摸事件的视图。在命中测试中,窗口在视图层次结构的最顶层视图上调用hitTest:withEvent:此方法通过在视图层次结构中返回YES的每个视图上递归调用pointInside:withEvent:继续执行,继续向下移动层次结构,直到找到触摸发生在其边界内的子视图。该视图成为热门测试视图。

  1. 创建UIView的子类。
  2. 覆盖hitTest:withEvent。
  3. 将此UIView子类用于superview。
  4. 在子类中添加以下方法:

    (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    {
        NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
        UIView *iSubView;
    
        while ((iSubView = [reverseE nextObject])) {
    
            UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
            if(viewWasHit) {
                return viewWasHit;
            }
    
        }
        return [super hitTest:point withEvent:event];
    }
    

    注意:由于子视图是从后到前排序的,因此我们希望首先测试最前面的视图。

答案 1 :(得分:2)

我发现这种情况的唯一解决方法是创建一个视图实例,该视图对于作为主视图的触摸是透明的。在这种情况下,内部视图将响应触摸,因为它适合主要的边界。在我通过网络中发现的不同示例制作的课程中,我可以控制“触摸可见性”的级别,如下所示: 完全可见 - 所有触摸最终都在视图中。 只有子视图 - 视图本身不可见,但子视图会触及它们。 完全看不见 - 我认为非常自我解释:)

我没有尝试将它与手势识别器一起使用,但我不认为会有任何问题,因为它与常规触摸完美配合。

代码很简单......

<强> TransparentTouchView.h

#import <UIKit/UIKit.h>

typedef enum{
    TransparencyTypeNone = 0,         //act like usual uiview
    TransparencyTypeContent,          //only content get touches
    TransparencyTypeFull              //fully transparent for touches
}TransparencyType;

@interface TransparentTouchView : UIView {
    TransparencyType      _transparencyType;
}

@property(nonatomic,assign)TransparencyType transparencyType;

@end

<强> TransparentTouchView.m

#import "TransparentTouchView.h"


@implementation TransparentTouchView

@synthesize 
transparencyType = _transparencyType;

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // UIView will be "transparent" for touch events if we return NO
    switch (_transparencyType) {
        case TransparencyTypeContent:
            for(UIView* subview in self.subviews){
                CGPoint p = [subview convertPoint:point fromView:self];
                if([subview pointInside:p withEvent:event]){
                    return YES;
                }
            }
            return NO;
            break;
        case TransparencyTypeFull:
            return NO;
        default:
            break;
    }
    return YES;
}

@end

我相信你可以满足你的需求。