Как включить одновременный выбор нескольких ячеек представления коллекции с помощью функции мультитач? - PullRequest
0 голосов
/ 26 января 2019

Я пишу карточную игру для iOS.Я отображаю карты игрока в виде коллекции.Игрок может выбрать одну или несколько карт, нажав на них, а затем нажать кнопку раздачи, чтобы сдать выбранные карты.

Я хочу разрешить пользователю использовать несколько пальцев для одновременного выбора нескольких карт.Например, если пользователь хочет выбрать 2 карты, ему просто нужно одновременно нажать на две карты двумя пальцами, и они будут выбраны обе.Похоже, что по умолчанию UICollectionView не позволяет этого.Когда я коснусь двумя пальцами, будет выбрана только одна из карт, хотя свойство isMultipleTouchEnabled в UIView уже установлено в значение true.

Обратите внимание, что я не спрашиваю о том, как разрешитьПользователь может выбрать несколько элементов в представлении коллекции.Я могу и уже сделал это с allowsMultipleSelection = true.Я спрашиваю, как разрешить пользователю выбирать 2 ячейки двумя пальцами (или n ячеек n пальцами).

Я нашел этот вопрос , но похоже, чточтобы показать границу вокруг ячейки, когда она выделена.

Я также изучил документацию UICollectionView, но не нашел ни одного свойства, управляющего этим.

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Вы можете добавить несколько распознавателей жестов для количества касаний, которые хотите поддерживать:

collectionView.allowsMultipleSelection = true
// allowing up to 5 finger touches, increase if you want for more :)
for i in 2...5 {
    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
    gestureRecognizer.numberOfTouchesRequired = i
    gestureRecognizer.delegate = self
    collectionView.addGestureRecognizer(gestureRecognizer)
}

, и попросите контроллер найти ячейки, к которым вы прикоснулись:

@objc private func handleTap(_ gestureRecognizer: UIGestureRecognizer) {
    // perform the action only after the touch ended
    guard gestureRecognizer.state == .ended else { return }

    for i in 0..<gestureRecognizer.numberOfTouches {
        let location = gestureRecognizer.location(ofTouch: i, in: collectionView)
        // if we have a cell at that point, toggle the selection
        if let indexPath = collectionView.indexPathForItem(at: location) {
            if collectionView.indexPathsForSelectedItems?.contains(indexPath) == true {
                collectionView.deselectItem(at: indexPath, animated: true)
            } else {
                collectionView.selectItem(at: indexPath, animated: true, scrollPosition: [])
            }
        }
    }
}
0 голосов
/ 30 января 2019

Для начала давайте точно поймем, в чем проблема.К 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
      }
    }
  }
}
...