在我的情况下,我解决了这个问题:
在这里我检测我的单元格是否完全可见,如果不可见-移动到它。(无需“跳跃”)
let cellRect = collectionView.convert(cell.frame, to: collectionView.superview)
if !collectionView.frame.contains(cellRect) {
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
return collectionView.reloadData()
}
这里,我保存了我的contentOffset:
let currentContentOffSet = collectionView.contentOffset
if #available(iOS 12.0, *) {
UIView.animate(withDuration: 0) {
collectionView.reloadData()
collectionView.performBatchUpdates(nil, completion: { _ in
collectionView.contentOffset = currentContentOffSet
})
}
} else {
UIView.animate(withDuration: 0) {
collectionView.reloadItems(at: [self.lastSelectedIndexPath, indexPath])
collectionView.contentOffset = currentContentOffSet
}
}
如果单元格最近变为可见状态(或已经可见),并且我点击该单元格,则可以使用它来移动到单元格。同时避免“跳动”(不重置contentOffset)。
在collectionViewController中,您也可以尝试这样做:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) else { return }
if lastSelectedIndexPath != indexPath {
let cellRect = collectionView.convert(cell.frame, to: collectionView.superview)
if !collectionView.frame.contains(cellRect) {
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
} else {
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .init())
}
collectionView.deselectItem(at: lastSelectedIndexPath, animated: false)
lastSelectedIndexPath = indexPath
}
}
这是在collectionViewCellModel中:
override var isSelected: Bool {
didSet {
switch self.isSelected {
case false:
case true:
}
}
}
UICollectionViewFlowLayout
覆盖collectionViewContentSize
以阻止偏移量的重置。 - luke