Обнаружить горизонтальное панорамирование в 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, который содержит таблицу;)
Ответы
Ответ 1
У меня была такая же проблема и вышло решение, которое работает с 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 velocityInView:cell].x < 600 && sqrt(translate...
Немного поработав на моем устройстве, я получил скорость от 500 до 600, что, на мой взгляд, дает лучший опыт для перехода между панорамированием и жестом салфетки к удалению.
Ответ 2
Мой ответ такой же, как у Флориана Милека, но я упростил и исправил его.
Как использовать:
Просто передайте 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);
}
Ответ 3
Вы можете попробовать использовать события касания вручную вместо распознавателей жестов. Всегда передавая событие обратно в таблицу, за исключением случаев, когда вы, наконец, распознаете жест прокрутки.
Каждый класс, который наследуется от UIResponder, будет иметь четыре сенсорные функции (начатые, завершенные, отмененные и перемещенные). Таким образом, самый простой способ "переслать" вызов - это обработать его в своем классе, а затем явно вызвать его на следующем объекте, с которым вы бы хотели его обработать (но вы должны убедиться, что он сначала отвечает на сообщение отвечаетToSelector: поскольку это необязательная функция). Таким образом, вы можете обнаружить любые события, которые вы хотите, а также обеспечить нормальное взаимодействие с любыми другими элементами.
Ответ 4
Может быть, вы можете использовать UISwipeGestureRecognizer
вместо этого? Вы можете сказать ему игнорировать прокрутки вверх/вниз с помощью свойства direction
.
Ответ 5
Спасибо за советы! В конце концов я пошел на подкласс UITableView, где я проверяю, является ли движение горизонтальным (в этом случае я использую свое обычное поведение), а также вызываю [super touchesMoved: withEvent:];.
Однако, я до сих пор не понимаю, почему это работает. Я проверил, и супер - UITableView. Похоже, я до сих пор не совсем понимаю, как работает эта иерархия. Может кто-нибудь попытаться объяснить?