Для начала давайте точно поймем, в чем проблема.К CollectionView прикреплено несколько UIGestureRecognisers (для панорамирования, касания, масштабирования и т. Д.).Каждый распознаватель имеет один и тот же конечный автомат возможного -> распознанного -> измененного -> завершенного / неисправного.Каждый распознаватель имеет четкое начало и конец.Как только жест касания начался в одном месте, он не будет начинаться в другом месте.Когда человек 1) касается точки вниз A 2) касается точки вниз B 3) касается точки вверх A 4) касается точки B, когда жест полностью игнорирует точку B, потому что он «сфокусирован» на точке A.
Вторая проблема заключается в том, что если вы коснетесь в двух точках в одно и то же время, метод tapGesture.location(in: view)
даст вам среднее значение из этих двух местоположений.
Однако мы решаем это, первым шагом является отключение collectionView.tapGesture - он не делает то, что мы хотим:
self.collectionView.allowsMultipleSelection = true
self.collectionView.allowsSelection = false;
Далее мы собираемся добавить свои собственные жесты касания к каждой ячейке индивидуально.Apple явно не рекомендует это («Вы всегда должны прикреплять свои распознаватели жестов к самому представлению коллекции, а не к определенной ячейке или представлению». 1 ), но это будет работать:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
...
cell.addGestureRecognizer(UITapGestureRecognizer.init(target: self, action: #selector(didTap(tapper:))))
...
return cell;
}
@objc func didTap(tapper:UIGestureRecognizer) {
if let cell = tapper.view as? UICollectionViewCell{
if let index = collectionView.indexPath(for: cell) {
if collectionView.indexPathsForSelectedItems?.contains(index) ?? false {
collectionView.deselectItem(at: index, animated: true)
cell.isSelected = false
}else{
collectionView.selectItem(at: index, animated: true, scrollPosition: [])
cell.isSelected = true
}
}
}
}