简体   繁体   English

UIScrollview窃取触摸事件

[英]UIScrollview stealing touch events

I have a subclassed UIView that implements touchesBegan, touchesMoved, touchesEnded . 我有一个子类的UIView ,它实现touchesBegan, touchesMoved, touchesEnded All is working well. 一切运行良好。 Then, I added a UIScrollview as subview to this UIVIew . 然后,我向此UIVIew添加了UIScrollview作为子视图。 Touches made within the UIScrollview are not forwarded back up the responder chain to the parent view , and so my UIView's touch methods are never called (they are called for touches made outside of the scrollview just fine). UIScrollview进行的触摸不会转发到响应者链上,返回到父视图 ,因此从不调用我的UIView的touch方法(只要在scrollview之外进行触摸就可以了)。

I created a new UIScrollView category like so: 我创建了一个新的UIScrollView类别,如下所示:

@implementation UIScrollView (forwardTouches)

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self.nextResponder touchesBegan: touches withEvent:event];
        [self setScrollEnabled:NO];
        NSLog(@"touchesBegan");
    }
    else{
        NSLog(@"touchesBegan-else");
        [super touchesEnded: touches withEvent: event];
    }
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self.nextResponder touchesMoved: touches withEvent:event];
        NSLog(@"touchesMoved");
    }
    else{
        NSLog(@"touchesMoved - else");
        [super touchesEnded: touches withEvent: event];
    }
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self.nextResponder touchesEnded: touches withEvent:event];
        [self setScrollEnabled:YES];
        NSLog(@"touchesEnded");
    }
    else{
        NSLog(@"touchesEnded - else");
        [super touchesEnded: touches withEvent: event];
    }
}

This actually seems to work as intended on the iPhone (which would be: if the user drags his finger across the scrollview, it scrolls, but if he places it on the view and does not move it, the parent view's touchesBegan method fires), but it does not work on the iPad. 实际上,这似乎可以在iPhone上正常工作(这是:如果用户在滚动视图上拖动手指,它会滚动,但是如果他将其放在视图上并且不移动它,则会触发父视图的touchesBegan方法),但不适用于iPad。 Presumably, self.dragging needs more time on the iPad, but I'm struggling to figure out a way to solve this reliably. 大概,在iPad上进行self.dragging需要更多时间,但是我正在努力寻找一种可靠地解决此问题的方法。 I'm sure I'm missing something very obvious. 我确定我遗漏了非常明显的东西。 Thanks in advance! 提前致谢!

EDIT WITH POSSIBLE SOLUTION: 使用可能的解决方案进行编辑:

I came up with the code below after some trial and error. 经过反复试验,我想到了下面的代码。 It seems to be working well on iPhone and iPad. 它在iPhone和iPad上似乎运行良好。 Any reasons why using this may be a bad idea? 使用此方法的任何原因可能是个坏主意?

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    NSArray * myDataArray = [NSArray arrayWithObjects:touches, event, nil];

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self performSelector:@selector(forwardTouches:) withObject:myDataArray afterDelay:0.5];
    }
    else{
        NSLog(@"touchesBegan-else");
        [super touchesEnded: touches withEvent: event];
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
}

-(void)forwardTouches:(NSArray *)array{
    NSSet * mySet = [array objectAtIndex:0];
    UIEvent * myEvent = [array objectAtIndex:1];

    if (!self.dragging){
        [self.nextResponder touchesBegan:mySet withEvent: myEvent];
        [self setScrollEnabled:NO];
    }
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self.nextResponder touchesMoved: touches withEvent:event];
        NSLog(@"touchesMoved");
    }
    else{
        NSLog(@"touchesMoved - else");
        [super touchesEnded: touches withEvent: event];
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{

    // If not dragging, send event to next responder
    if (!self.dragging){
        [self.nextResponder touchesEnded: touches withEvent:event];
        [self setScrollEnabled:YES];
        NSLog(@"touchesEnded");
    }
    else{
        NSLog(@"touchesEnded - else");
        [super touchesEnded: touches withEvent: event];
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
}

The code above is not a good plan. 上面的代码不是一个好的计划。 If you want to super view got a chance to handle the touch which appear in the subview , you should use gesture , not changing the forwarding of the touch , It's dangerous. 如果要超级视图有机会处理出现在子视图中的触摸,则应使用手势,而不要更改触摸的前进,这很危险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM