With collectionView.isPagingEnabled = true 如何知道分页何时完成
With collectionView.isPagingEnabled = true how to know when paging is completed
我有一个与 collectionView 大小相同的垂直方向单元格,我设置了 collectionView.isPagingEnabled = true
。屏幕上一次只有 1 个活动可见单元格:
layout.scrollDirection = .vertical
collectionView.isPagingEnabled = true
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// collectionView is the same width and height as the device
let width = collectionView.frame.width
let height = collectionView.frame.height
return CGSize(width: width, height: height)
}
我需要知道用户上下滑动后整个单元格何时显示在屏幕上(当页面完成分页并在屏幕上居中时)。或者换句话说,我需要知道用户何时没有在单元格之间滑动或拖动。我试过这个:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate {
if scrollView.frame.height == collectionView.frame.height {
let indexPaths = collectionView.indexPathsForVisibleItems
for indexPath in indexPaths {
if let cell = collectionView.cellForItem(at: indexPath) as? MyCell {
print("currentCell: \(indexPath.item)") // do something in cell
}
}
}
}
}
我 运行 遇到的问题是,即使我以 1/2 的方式拖动,这意味着如果我在项目 2 上,将 1/2 拖动到项目 3,然后再拖回项目 2,print("currentCell: \(indexPath.item)")
将打印出 currentCell: 3
然后 currentCell: 2
。它应该打印 currentCell: 3
的唯一时间是如果该单元格完全在屏幕上而不是在单元格 2 和 3(或 2 和 1 等)之间。
你可以使用:
var currentCellIndexPath: IndexPath? = nil {
didSet {
guard oldValue != currentCellIndexPath else { return }
// Get the cell
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
let candidate = ratio.rounded()
guard abs(candidate - ratio) < 0.1 else { return }
guard collectionView.indexPathsForVisibleItems.count > 1 else {
guard !collectionView.indexPathsForVisibleItems.isEmpty else {
return
}
currentCellIndexPath = collectionView.indexPathsForVisibleItems[0]
}
let firstIdx = collectionView.indexPathsForVisibleItems[0]
let secondIdx = collectionView.indexPathsForVisibleItems[1]
if candidate > ratio {
currentCellIndexPath = secondIdx > firstIdx ? secondIdx : firstIdx
} else {
currentCellIndexPath = secondIdx > firstIdx ? firstIdx : secondIdx
}
}
另一种解决方案,对于您的情况,您在 collectionView.indexPathsForVisibleItems 中最多有 2 个索引路径。
因此,如果有两个索引路径,您只需检查哪一个是正确的。
您可以通过以下方式查看:
let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
let isUpper = ratio - CGFloat(Int(ratio)) > 0.5
那么如果isUpper = true,它就是数组中的第二个indexPath。
您可以尝试这样的操作:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let y = targetContentOffset.pointee.y
let item = Int(y / view.frame.height)
print("current cell: \(item)")
}
在这段代码中,我使用框架的宽度来划分 x,因为我的 collectionView 是水平的,您可以使用高度作为垂直轴。希望对你有帮助
我有一个与 collectionView 大小相同的垂直方向单元格,我设置了 collectionView.isPagingEnabled = true
。屏幕上一次只有 1 个活动可见单元格:
layout.scrollDirection = .vertical
collectionView.isPagingEnabled = true
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// collectionView is the same width and height as the device
let width = collectionView.frame.width
let height = collectionView.frame.height
return CGSize(width: width, height: height)
}
我需要知道用户上下滑动后整个单元格何时显示在屏幕上(当页面完成分页并在屏幕上居中时)。或者换句话说,我需要知道用户何时没有在单元格之间滑动或拖动。我试过这个:
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate {
if scrollView.frame.height == collectionView.frame.height {
let indexPaths = collectionView.indexPathsForVisibleItems
for indexPath in indexPaths {
if let cell = collectionView.cellForItem(at: indexPath) as? MyCell {
print("currentCell: \(indexPath.item)") // do something in cell
}
}
}
}
}
我 运行 遇到的问题是,即使我以 1/2 的方式拖动,这意味着如果我在项目 2 上,将 1/2 拖动到项目 3,然后再拖回项目 2,print("currentCell: \(indexPath.item)")
将打印出 currentCell: 3
然后 currentCell: 2
。它应该打印 currentCell: 3
的唯一时间是如果该单元格完全在屏幕上而不是在单元格 2 和 3(或 2 和 1 等)之间。
你可以使用:
var currentCellIndexPath: IndexPath? = nil {
didSet {
guard oldValue != currentCellIndexPath else { return }
// Get the cell
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
let candidate = ratio.rounded()
guard abs(candidate - ratio) < 0.1 else { return }
guard collectionView.indexPathsForVisibleItems.count > 1 else {
guard !collectionView.indexPathsForVisibleItems.isEmpty else {
return
}
currentCellIndexPath = collectionView.indexPathsForVisibleItems[0]
}
let firstIdx = collectionView.indexPathsForVisibleItems[0]
let secondIdx = collectionView.indexPathsForVisibleItems[1]
if candidate > ratio {
currentCellIndexPath = secondIdx > firstIdx ? secondIdx : firstIdx
} else {
currentCellIndexPath = secondIdx > firstIdx ? firstIdx : secondIdx
}
}
另一种解决方案,对于您的情况,您在 collectionView.indexPathsForVisibleItems 中最多有 2 个索引路径。
因此,如果有两个索引路径,您只需检查哪一个是正确的。 您可以通过以下方式查看:
let ratio = scrollView.contentOffset.y / scrollView.contentSize.height
let isUpper = ratio - CGFloat(Int(ratio)) > 0.5
那么如果isUpper = true,它就是数组中的第二个indexPath。
您可以尝试这样的操作:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let y = targetContentOffset.pointee.y
let item = Int(y / view.frame.height)
print("current cell: \(item)")
}
在这段代码中,我使用框架的宽度来划分 x,因为我的 collectionView 是水平的,您可以使用高度作为垂直轴。希望对你有帮助