Обнаружить горизонтальное панорамирование в UITableView

Я использую UIPanGestureRecognizer для распознавания горизонтального скольжения в UITableView (в ячейке, если быть точным, хотя он добавлен к самой таблице). Однако этот распознаватель жестов, очевидно, крадет штрихи со стола. Я уже получил признак pangesturer для распознавания горизонтального скольжения, а затем привязался к этому; но если пользователь начинает с разворота по вертикали, он должен передавать все события от этого касания к таблице.

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

Еще одна вещь, которую я пробовал, заключалась в том, чтобы заставить ее прокручивать себя, но тогда вы будете пропустить постоянную скорость после остановки прикосновения.

Вот какой код:

//In the viewdidload method
UIPanGestureRecognizer *slideRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(sliding:)];
[myTable addGestureRecognizer:slideRecognizer];
-(void)sliding:(UIPanGestureRecognizer *)recognizer
{
 if (recognizer.state == UIGestureRecognizerStateBegan)
 {
 CGPoint translation = [recognizer translationInView:favoritesTable];
 if (sqrt(translation.x*translation.x)/sqrt(translation.y*translation.y)>1) {
 horizontalScrolling = YES; //BOOL declared in the header file
 NSLog(@"horizontal");
 //And some code to determine what cell is being scrolled:
 CGPoint slideLocation = [recognizer locationInView:myTable];
 slidingCell = [myTable indexPathForRowAtPoint:slideLocation];
 if (slidingCell.row == 0) {
 slidingCell = nil;
 }
 }
 else
 {
 NSLog(@"cancel");
 }
 if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled)
 {
 horizontalScrolling = NO;
 }
 if (horizontalScrolling)
 {
 //Perform some code
 }
 else
 {
 //Maybe pass the touch from here; It panning vertically
 }
}

Итак, какие-либо советы о том, как передать прикосновения?

Дополнение: Я также подумал, что, возможно, подкласс метода распознавания жестов tableview, чтобы сначала проверить, является ли он горизонтальным; Однако тогда мне понадобится исходный код, я полагаю... Не знаю, будет ли у Apple проблемы с ним. Кроме того: я не подклассифицировал UITableView (контроллер), а только ячейки. Этот код находится в viewcontroller, который содержит таблицу;)

5 ответов

У меня была такая же проблема и вышло решение, которое работает с UIPanGestureRecognizer.

В отличие от Erik я добавил UIPanGestureRecognizer в ячейку напрямую, так как мне нужна только одна конкретная ячейка сразу для поддержки панорамирования. Но я предполагаю, что это должно работать и на случай Эрика.

Здесь код.

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
 UIView *cell = [gestureRecognizer view];
 CGPoint translation = [gestureRecognizer translationInView:[cell superview]];
 // Check for horizontal gesture
 if (fabsf(translation.x) > fabsf(translation.y))
 {
 return YES;
 }
 return NO;
}

Вычисление горизонтального жеста копируется из кода Erik - я тестировал это с помощью iOS 4.3.

Edit: Я узнал, что эта реализация предотвращает жест "салфетки для удаления". Чтобы восстановить это поведение, я добавил проверку скорости жестов на if-statement выше.

if ([gestureRecognizer **************:cell].x < 600 && sqrt(translate...

Немного поработав на моем устройстве, я получил скорость от 500 до 600, что, на мой взгляд, дает лучший опыт для перехода между панорамированием и жестом салфетки к удалению.


Мой ответ такой же, как у Флориана Милека, но я упростил и исправил его.

Как использовать:

Просто передайте UIPanGestureRecognizer делегату (UIGestureRecognizerDelegate). Например:

UIPanGestureRecognizer *panner = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDetected:)];
panner.delegate = self;
[self addGestureRecognizer:panner];

Затем этот делегат реализует следующий метод:

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
 CGPoint translation = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:gestureRecognizer.view.superview];
 return fabsf(translation.x) > fabsf(translation.y);
}


Вы можете попробовать использовать события касания вручную вместо распознавателей жестов. Всегда передавая событие обратно в таблицу, за исключением случаев, когда вы, наконец, распознаете жест прокрутки.

Каждый класс, который наследуется от UIResponder, будет иметь четыре сенсорные функции (начатые, завершенные, отмененные и перемещенные). Таким образом, самый простой способ "переслать" вызов - это обработать его в своем классе, а затем явно вызвать его на следующем объекте, с которым вы бы хотели его обработать (но вы должны убедиться, что он сначала отвечает на сообщение отвечаетToSelector: поскольку это необязательная функция). Таким образом, вы можете обнаружить любые события, которые вы хотите, а также обеспечить нормальное взаимодействие с любыми другими элементами.


Может быть, вы можете использовать UISwipeGestureRecognizer вместо этого? Вы можете сказать ему игнорировать прокрутки вверх/вниз с помощью свойства direction.


Спасибо за советы! В конце концов я пошел на подкласс UITableView, где я проверяю, является ли движение горизонтальным (в этом случае я использую свое обычное поведение), а также вызываю [super touchesMoved: withEvent:];.

Однако, я до сих пор не понимаю, почему это работает. Я проверил, и супер - UITableView. Похоже, я до сих пор не совсем понимаю, как работает эта иерархия. Может кто-нибудь попытаться объяснить?

licensed under cc by-sa 3.0 with attribution.