UICollectionView использует вертикальный жест панорамирования

#ios #uicollectionview #uiscrollview #uigesturerecognizer #uicollectionviewflowlayout

Вопрос:

У меня есть UICollectionView, который находится внутри UITableView и находится внутри UIScrollView. Представление коллекции представляет собой горизонтально прокручивающуюся карусель элементов, и это прекрасно работает, если в представлении коллекции достаточно элементов, чтобы оно было шире ширины экрана. Но проблема, с которой я сталкиваюсь, заключается в том, что если есть только один или два элемента (недостаточно для заполнения ширины экрана), то представление коллекции, похоже, использует жест вертикального панорамирования и не позволяет прокручивать представление прокрутки.

Именно так в настоящее время устроено мое приложение. Существует вид прокрутки (зеленый на следующем рисунке), который содержит все содержимое страницы. Внутри этого есть табличное представление, которое имеет несколько разделов. Каждый раздел имеет заголовок раздела, который можно использовать. При нажатии на заголовок раздела раздел расширяется, добавляя одну строку, содержащую представление коллекции. Представление коллекции представляет собой представление коллекции компоновки потока с горизонтальной прокруткой.

введите описание изображения здесь

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

введите описание изображения здесь

Код

Вот код для инициализации представления коллекции:

 - (UICollectionView *)collectionView {
    if (!self->_collectionView) {
        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        layout.minimumInteritemSpacing = 10;
        layout.minimumLineSpacing = 10;
        
        layout.sectionInset = UIEdgeInsetsMake(0, 16, 0, 16);
        layout.sectionInsetReference = UICollectionViewFlowLayoutSectionInsetFromContentInset;
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        
        self->_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
        self->_collectionView.translatesAutoresizingMaskIntoConstraints = NO;
        self->_collectionView.backgroundColor = nil;
        self->_collectionView.delegate = self;
        self->_collectionView.dataSource = self;
        
        [self.collectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@"MyCollectionViewCell"];
    }
    return self->_collectionView;
}
 

Вопрос

Кто-нибудь знает, почему представление коллекции будет использовать жест вертикального панорамирования, когда есть только один или два элемента, или как это исправить?

Ответ №1:

Все три вида на самом деле являются видами прокрутки. UITableView и UICollectionView классы наследуются от UIScrollView .

UIScrollView распознает прокрутку с помощью its panGestureRecognizer .

Поскольку вы не определяете зависимости между этими распознавателями в ваших представлениях прокрутки, событие касания используется следующим образом:

  • все распознаватели получают прикосновение (вот как они предварительно настроены UIScrollView )
  • если распознаватель проверенного представления не дает сбоя, он обрабатывает жест панорамирования
  • если это не удается, распознаватель супервизора пытается обработать жест.

И эта каскадная обработка панорамирования идет вверх по иерархии представлений таким образом, пока жест не будет обработан или больше не будет просмотров прокрутки.

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

Вы можете попробовать две вещи по этому поводу. Либо требуется сбой распознавателя панорамирования вида прокрутки для распознавателя панорамирования вида коллекции

 [self->_collectionView.panGestureRecognizer requireGestureRecognizerToFail:scrollView.panGestureRecognizer]
 

или отключите прокрутку представления коллекции, если размер содержимого в нем меньше границ. Для этого вы можете создать подкласс UICollectionView , переопределить setContentSize: и setBounds: методы и назначить scrollEnabled их соответствующим образом. Затем используйте свой подкласс вместо ванили UICollectionView .

Комментарии:

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

2. Я понятия не имею, почему это происходит. Представление коллекции внутри табличного представления-это обычный сценарий, который используют многие приложения. Для первого решения вы также можете проверить, есть ли у обоих распознавателей .delegate == nil , и если да, назначьте self их в качестве делегатов, а также реализуйте gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) и возвращайте true . Это может предотвратить задержки.