将UIGesture转发给背后的观点

Kri*_*dra 57 iphone touch ipad uigesturerecognizer ios

我正在开发iphone(iOS 4.0或更高版本)应用程序,并且在多个视图之间处理触摸问题.我有这样的视图结构

---> A superView 
     |
     ---> SubView - A 
     |
     ---> SubView - B (exactly on top of A, completely blocking A).
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

基本上我有一个superView和兄弟子视图A和B. B与A具有相同的框架,因此完全隐藏了A.

现在我的要求就是这个.

  1. SubView B应该接收所有滑动和点按(单和双)手势.
  2. SubView A应该接收所有捏合手势.

这就是我为视图添加手势识别器的方法

UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
[leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
leftSwipe.delegate  =   self;
[bView addGestureRecognizer:leftSwipe];
[leftSwipe release];

UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
[rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
rightSwipe.delegate   =   self;
[bView addGestureRecognizer:rightSwipe];
[rightSwipe release];

UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
pinch.delegate    =   self;
[aView addGestureRecognizer:pinch];
[pinch release];
Run Code Online (Sandbox Code Playgroud)

我做了一些研究,对我UIGestureRecognizerDelegate看起来很有希望,我实现了委托方法

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
Run Code Online (Sandbox Code Playgroud)

我为SubView B返回NO,希望底层视图能够获得这些事件.没有这样的运气

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] && [gestureRecognizer view] == bView) {
        NSLog(@"pinchGesture");
        //bView.userInteractionEnabled = NO;
        return NO;
    }
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

然后我在委托回调(上面的块中注释的代码)中禁用了SubView B的用户交互,当识别到捏合手势时,希望剩余部分的手势将被SubView A接收.也没有这样的运气......

这就是我现在所处的位置.我已经看到了这个问题,其中接受的答案涉及财产cancelsTouchesInView.但我相信cancelsTouchesInView只取消特定的触摸事件,不要转发它.

还有其他方式来达到我的要求吗?我准备好处理你提供的任何暗示.

编辑:BOUNTY TIME

我所谓的subView A实际上是第三方库的View类的一个实例,它接受了所有触摸,我对它上面的任何手势都没有任何控制权.我想要左右滑动的不同实现,我想要捏,点击等工作,就像它正在使用这个第三方视图.所以我在A(SubView B)的顶部放置了一个视图以获得左右滑动.但现在我想将其他手势事件转发给底层库.

Sen*_*neL 18

如果我没有正确解决您的问题,您可以添加另一个清晰的视图,使用rect,与A和B视图相同,并在其上实现所有手势:当您执行捏合手势时,控制子视图A,当滑动并点按(单个和double)手势 - 控制子视图B.你可以采用不同的方式:通过指针或只是将重复的手势发送到类中的方法,它控制你的子视图.

例如:

UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
[leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
leftSwipe.delegate  =   subViewAcontroller;
[clearView addGestureRecognizer:leftSwipe];
[leftSwipe release];

UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
[rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
rightSwipe.delegate   =   subViewAcontroller;
[clearView addGestureRecognizer:rightSwipe];
[rightSwipe release];

UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
pinch.delegate    =   subViewBcontroller;
[clearView addGestureRecognizer:pinch];
[pinch release];
Run Code Online (Sandbox Code Playgroud)

要么:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
        NSLog(@"pinchGesture");
        [subViewBcontroller solvePinchGesture: gestureRecognizer];
    }
//etc
    return YES;
}
Run Code Online (Sandbox Code Playgroud)


fly*_*pig 15

aView永远不会收到捏合手势,因为您查看的层次结构不正确.

---> A superView 
 |
 ---> SubView - A 
 |
 ---> SubView - B (exactly on top of A, completely blocking A).
Run Code Online (Sandbox Code Playgroud)

bView将捕获所有多点触摸,包括捏合手势,但bView将不会处理捏合手势,因此它会将其传递给Responder链中的Next响应者,即bView的superView或bView的viewController.pinch事件永远不会传递给它的兄弟视图,因为它们是并行的(没有parent-child或view-viewController关系).

您可以更改视图层次结构,如下所示:

---> A superView 
 |
 ---> SubView - A 
       |
       ---> SubView - B (child view of b, exactly on top of A, completely blocking A)



- (void)viewDidLoad {
    [super viewDidLoad];

    aView = [[UIView alloc] initWithFrame:self.view.bounds];
    aView.backgroundColor = [UIColor blueColor];

    bView = [[UIView alloc] initWithFrame:self.view.bounds];
    bView.backgroundColor = [UIColor redColor];

    [self.view addSubview:aView];
    [aView addSubview:bView];

    UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
    [leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    leftSwipe.delegate  =   self;
    [bView addGestureRecognizer:leftSwipe];

    UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
    [rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
    rightSwipe.delegate   =   self;
    [bView addGestureRecognizer:rightSwipe];

    UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
    pinch.delegate    =   self;
    [aView addGestureRecognizer:pinch];
}
Run Code Online (Sandbox Code Playgroud)

请从以下链接获取更多信息:https: //developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/EventsiPhoneOS/EventsiPhoneOS.html#//apple_ref/doc/uid/TP40009541-CH2-SW1

- >在响应者链中传递事件的重要说明"当系统发送触摸事件时,它首先将其发送到特定视图.对于触摸事件,该视图是hitTest返回的视图:withEvent:;用于"摇动" - 运动事件,远程控制事件,动作消息和编辑菜单消息,该视图是第一个响应者.如果初始视图不处理该事件,它将沿着特定路径沿着响应者链向上移动:

  1. 命中测试视图或第一响应者将事件或消息传递给其视图控制器(如果有); 如果视图没有视图控制器,它会将事件或消息传递给其超级视图.
  2. 如果视图或其视图控制器无法处理事件或消息,则会将其传递给视图的超级视图.
  3. 如果层次结构无法处理事件或消息,则层次结构中的每个后续超级视图都遵循前两个步骤中描述的模式.
  4. 视图层次结构中最顶层的视图,如果它不处理事件或消息,则将其传递给窗口对象进行处理.
  5. UIWindow对象,如果它不处理事件或消息,则将其传递给单例应用程序对象."

我上面的答案不是唯一的解决方案,你需要做的是在同一个响应者链中进行滑动和捏合手势处理逻辑,因此非句柄捏手势事件将传递给正确的响应者.例如,您可以省略子视图b,并将滑动左/右手势添加到aView的superView.