我正在编写iOS纸牌游戏。我在收藏夹视图中显示玩家的纸牌。玩家可以通过点击选择一张或多张纸牌,然后按交易按钮来发行选定的纸牌。
我想允许用户使用多个手指一次选择多个卡。例如,如果用户要选择2张卡,他只需要用两个手指同时点击两张卡,就可以同时选择它们。似乎默认情况下,UICollectionView
不允许这样做。当我用两根手指轻按时,即使isMultipleTouchEnabled
中的UIView
属性已设置为true,也只会选择其中一张。
请注意,我并不是在问如何允许用户在集合视图中选择多个项目。我可以并且已经使用allowsMultipleSelection = true
来做到这一点。我要问的是如何允许用户选择2个手指的2个单元格(或n个手指的n个单元格)。
我找到了这个question,但这似乎与如何在选定单元格周围显示边框有关。
我还研究了UICollectionView
的文档,但没有找到可控制它的属性。
答案 0 :(得分:7)
首先,让我们确切地了解问题所在。 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;
接下来,我们将向每个单元格分别添加自己的点击手势。苹果显然不建议这样做(“您应该始终将手势识别器附加到集合视图本身上,而不是附加到特定的单元格或视图上。” 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
}
}
}
}
答案 1 :(得分:3)
您可以为要支持的触摸次数添加多个手势识别器:
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: [])
}
}
}
}