UIScrollView предотвращает прикосновения

Я обрабатываю касания для пары моих компонентов пользовательского интерфейса в моем контроллере представления (пользовательский подкласс UIViewController). У него есть методы touchesBegan:withEvent:, touchesMoved:withEvent:, а также touchesEnded:withEvent:, Работало нормально. Затем я добавил представление прокрутки (UIScrollView) как вид сверху в иерархии.

Теперь мои сенсорные обработчики на контроллере вида не работают. Им не звонят. Интересно то, что у меня есть несколько других компонентов пользовательского интерфейса в представлении прокрутки, которые работают. Некоторые из них являются кнопками, некоторые являются пользовательскими представлениями, которые определяют их собственные touchesBegan:withEvent:и т. д. Единственное, что не работает - это сенсорные обработчики на контроллере вида.

Я подумал, может быть, это потому, что представление прокрутки перехватывает эти прикосновения для своих собственных целей, но я подкласс UIScrollView и просто посмотреть, смогу ли я заставить его работать, я возвращаю YES всегда из touchesShouldBegin:withEvent:inContentView: а также NO всегда из touchesShouldCancelInContentView:, Все еще не работает.

Если это имеет значение, мой контроллер представления находится в контроллере панели вкладок, но я не думаю, что это актуально.

У кого-нибудь была эта проблема и есть готовое решение? Я предполагаю, что представление прокрутки обезьяны вверх по цепочке респондента. Могу ли я вернуть его обратно? Полагаю, что если я не смогу что-либо еще выяснить, я сделаю вид верхнего уровня под моим видом прокрутки как пользовательский вид и перенаправлю сообщения на контроллер представления, но это выглядит глупо.

5 ответов

Создайте подкласс класса 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];
   }
}

Ну, это сработало, но я не уверен, что смогу "сойти с рук", поскольку 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

Затем в Интерфейсном Разработчике я сделал прямое подпредставление представления прокрутки одним из них и подключил его 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];
}

"Это работало нормально. Затем я добавил представление прокрутки (UIScrollView) как вид сверху в иерархии".

Ваше прокручиваемое представление поверх вашего содержимого, которое содержит элементы?

все ваши компоненты должны быть в просмотре прокрутки, а не в представлении позади просмотра прокрутки

Ответ user1085093 работал для меня. Однако, когда вы перемещаете касание больше, чем на небольшое количество, оно интерпретируется как пан-жест.

Я преодолел это, изменив поведение распознавателя 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;
        }
    }

}

touchesBegan: Методы etc никогда не будут вызываться в UIScrollView потому что это подкласс UIView и переопределяет эти методы. проверить разные UIScrollView методы доступны здесь. Обходной путь будет зависеть от того, что вы хотите реализовать.

Другие вопросы по тегам