我正在努力应对让多个手势识别器很好地协同工作的棘手挑战。基本上我正在尝试实现类似于Apple的原生Drag& amp;在iOS 11中引入的丢弃行为。由于各种原因(主要是拖延时间的长时间延迟)本机API不适合我们的用例,所以我正在尝试实现自定义行为。
我有一个全屏UICollectionView,我希望用两根手指平移。这可以通过collectionView.panGestureRecognizer.minimumNumberOfTouches = 2
此collectionView的父级还附加了一个panGestureRecognizer,maximumNumberOfTouches = 1
。这个识别器处理诸如拾取子视图和拖动它们以及移动(一个手指)触摸之类的东西。到现在为止还挺好。我可以选择一些东西,拖动它,然后(当第一次拖动仍在进行时)使用两个手指平移collectionView,而拖动的项目在父级的视图层次中保持可见。
现在出现了问题:一旦collectionView上的平移已经结束,只要我不放开第一个手指(与另一个平移手势相关的手指),collectionView就会保持无响应状态。除非我结束第一个手势,否则它将无法识别任何进一步的双指平底锅。
我对此进行了一系列调试,似乎在手势结束后,collectionView的panGestureRecognizer的内部状态未被重置为.possible
。我已经尝试了很多东西来解决这个问题,即使是最讨厌和奇怪的想法,但我只是无法解决这个问题。对此的任何想法都将受到无限的赞赏。
我将问题分离到一个小的UIViewController子类中,可以将其抛入一个空项目中以重现该问题:
import UIKit
class ViewController: UIViewController, UIGestureRecognizerDelegate, UICollectionViewDataSource {
var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = view.bounds.size
flowLayout.minimumLineSpacing = 0
flowLayout.minimumInteritemSpacing = 0
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: flowLayout)
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
collectionView.dataSource = self
collectionView.isPagingEnabled = true
collectionView.panGestureRecognizer.minimumNumberOfTouches = 2
view.addSubview(collectionView)
let panRec = UIPanGestureRecognizer(target: self, action: #selector(didOneFingerPan(_:)))
panRec.delegate = self
panRec.maximumNumberOfTouches = 1
view.addGestureRecognizer(panRec)
}
@objc func didOneFingerPan(_ rec: UIPanGestureRecognizer) {
print("didOneFingerPan: \(rec.state.rawValue)")
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.backgroundColor = indexPath.item % 2 == 0 ? .yellow : .red
return cell
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}