【问题标题】:UIScrollview stealing touch eventsUIScrollview 窃取触摸事件
【发布时间】:2013-12-03 04:12:19
【问题描述】:

我有一个实现touchesBegan, touchesMoved, touchesEnded 的子类UIView。一切运作良好。然后,我在这个UIVIew 中添加了一个UIScrollview 作为子视图。在UIScrollview 中进行的触摸是not forwarded back up the responder chain to the parent view,因此我的 UIView 的触摸方法永远不会被调用(它们被调用用于在滚动视图之外进行的触摸就好了)。

我像这样创建了一个新的 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];
    }
}

这实际上似乎在 iPhone 上按预期工作(即:如果用户将手指拖过滚动视图,它会滚动,但如果他将手指放在视图上并且不移动它,则父视图的 touchesBegan 方法火灾),但它不适用于 iPad。据推测,self.dragging 需要更多时间在 iPad 上,但我正在努力寻找可靠解决此问题的方法。我确定我遗漏了一些非常明显的东西。提前致谢!

使用可能的解决方案进行编辑:

经过反复试验,我想出了下面的代码。它似乎在 iPhone 和 iPad 上运行良好。为什么使用它可能是个坏主意?

-(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];
    }
}

【问题讨论】:

  • 您是否只是想在父视图中捕获点击事件而不中断滚动视图中的滚动?
  • 我试图得到一个非此即彼的场景。如果用户将手指按在屏幕上并且不移动它,我希望 UIView 中的触摸方法触发,并且滚动视图不滚动。如果用户在屏幕上按下手指并移动它,我希望 UIScrollview 滚动,并且 UIView 的触摸方法不触发。

标签: ios iphone objective-c uiview uiscrollview


【解决方案1】:

上面的代码不是一个好的计划。 如果你想让超级视图有机会处理子视图中出现的触摸,你应该使用手势,而不是改变触摸的转发,这是危险的。

【讨论】:

  • 由于多种原因,我无法将超级视图的代码更改为使用手势。我可以使用手势识别器来拦截滚动视图中的触摸,并将其转发给超级视图的触摸方法吗?
  • UITapGestureRecognizer 可以满足您的需求吗?给superview添加一个UITapGestureRecognizer;当用户点击时,调用superview,当用户滚动时,调用scrollView;
  • 是的,这可行,但我不确定如何在代码中实现。
  • 详细说明 - 我可以轻松地将 UIGestureRecognizer 添加到视图控制器。但我不知道如何将调用传递给(自定义)视图,以及如何将其转换为它的触摸......方法?
  • 没关系,我想通了。我必须将 UIGestureRecognizer 放入 UIView 的 awakefromnib,而不是控制器。
猜你喜欢
  • 2011-06-05
  • 2011-07-10
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
相关资源
最近更新 更多