UIScrollView阻止了视图控制器上的touchesBegan,touchesMoved,touchesEnded

时间:2011-09-16 01:32:25

标签: iphone uiscrollview touch viewcontroller nsresponder

我正在处理视图控制器(UIViewController的自定义子类)中的几个UI组件。它有方法touchesBegan:withEvent:touchesMoved:withEvent:touchesEnded:withEvent:。它工作正常。然后我添加了一个滚动视图(UIScrollView)作为层次结构中的顶视图。

现在我在视图控制器上的触摸处理程序不起作用。他们没有被召唤。有趣的是,我在滚动视图中有各种其他UI组件可以正常工作。有些是按钮,有些是自定义视图,用于定义自己的touchesBegan:withEvent:等。唯一不起作用的是视图控制器上的触摸处理程序。

我想也许是因为滚动视图为了自己的目的拦截了那些触摸,但是我将UIScrollView子类化,只是为了看看我是否可以让它工作我总是从YES返回touchesShouldBegin:withEvent:inContentView: NO始终来自touchesShouldCancelInContentView:。仍然无效。

如果它有所不同我的视图控制器在标签栏控制器内,但我认为它不相关。

有没有人遇到过这个问题并且有一个现成的解决方案?我的猜测是滚动视图猴子响应者链。我可以回来吗?我想如果我无法想出任何其他内容,我会将滚动视图下的顶级视图设为自定义视图并将消息转发给视图控制器,但看起来很糟糕。

5 个答案:

答案 0 :(得分:22)

创建UIScrollView类的子类并覆盖touchesBegan:和其他触摸方法,如下所示:

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

// If not dragging, send event to next responder
  if (!self.dragging){ 
    [self.nextResponder touchesBegan: touches withEvent:event]; 
  }
  else{
    [super touchesBegan: 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]; 
   }
   else{
     [super touchesMoved: 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]; 
   }
   else{
     [super touchesEnded: touches withEvent: event];
   }
}

答案 1 :(得分:2)

这很有用,但我不确定我能“逃脱它”,因为nextResponder不是你被“鼓励”在子类中覆盖的UIView方法之一。

@interface ResponderRedirectingView : UIView {

    IBOutlet UIResponder *newNextResponder;

}

@property (nonatomic, assign) IBOutlet UIResponder *newNextResponder;

@end


@implementation ResponderRedirectingView

@synthesize newNextResponder;

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

- (UIResponder *)nextResponder {
    return self.newNextResponder;
}

- (void)dealloc
{
    [super dealloc];
}

@end

然后在Interface Builder中,我将滚动视图的直接子视图中的一个作为其中一个,并连接其newNextResponder以跳过滚动视图并直接指向视图控制器。

这也有效,用这些覆盖替换了nextResponder的覆盖:

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.newNextResponder touchesBegan:touches withEvent:event];
}

- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.newNextResponder touchesMoved:touches withEvent:event];
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.newNextResponder touchesEnded:touches withEvent:event];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.newNextResponder touchesCancelled:touches withEvent:event];
}

答案 2 :(得分:0)

“它运行正常。然后我添加了一个滚动视图(UIScrollView)作为层次结构中的顶视图。”

是您的内容视图顶部的滚动视图,其中包含项目?

所有组件都应该在滚动视图中,而不是滚动视图后面的视图

答案 3 :(得分:0)

user1085093的回答对我有用。然而,一旦您将触摸移动了一小部分,它就会被解释为Pan Gesture。

我通过改变Pan Gesture识别器的行为克服了这一点,因此它需要两个手指:

-(void)awakeFromNib
{
    NSArray                 *gestureRecognizers = self.gestureRecognizers;
    UIGestureRecognizer     *gestureRecognizer;

    for (gestureRecognizer in gestureRecognizers) {
        if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
            UIPanGestureRecognizer      *pgRecognizer = (UIPanGestureRecognizer*)gestureRecognizer;
            pgRecognizer.minimumNumberOfTouches = 2;
        }
    }

}

答案 4 :(得分:-1)

touchesBegan:等方法将在UIScrollView中调用 NEVER ,因为它是UIView的子类并覆盖这些方法。查看可用的UIScrollView种不同方法here。解决方法取决于您要实施的内容。