【问题标题】:How to get the horizontal scroll percentage using UICollectionViewCompositionalLayout?如何使用 UICollectionViewCompositionalLayout 获取水平滚动百分比?
【发布时间】:2021-09-29 02:59:48
【问题描述】:

问题

如何使用组合布局获得水平集合视图部分的完整可滚动内容宽度?

详情

我正在使用组合布局实现UICollectionView,因此我可以获得良好而简单的section.orthogonalScrollingBehavior = .groupPaging 行为。但是,我还需要知道用户滚动浏览该部分的百分比,以便我可以保持自定义 PageControl 同步。对于使用UICollectionViewFlowLayout 的其他集合视图,这是一个简单的计算:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let scrollProgress = scrollView.contentOffset.x / scrollView.contentSize.width
    pageControl.currentPercentage = scrollProgress 

我已经learned 需要使用visibleItemsInvalidationHandler 而不是这个委托方法。我的问题是,对于组合布局,layoutEnvironment.container.contentSize.widthcollectionView.contentSize.width 的值不再是 scrollable 内容的全宽,它现在等于 collectionView 本身的框架。不过,scrollOffset 的值,就完整的可滚动内容大小而言。

section.visibleItemsInvalidationHandler = { [weak self] visibleItems, scrollOffset, layoutEnvironment in
    guard let self = self else { return }
    let contentWidth = layoutEnvironment.container.contentSize.width // not the full content width
    //let contentWidth = self.collectionView.contentSize.width // neither is this!
    let scrollProgress = scrollPosition / contentWidth
    self.pageControl.currentPercentage = scrollProgress
}

我尝试在layoutEnvironment 中进行挖掘,但没有发现任何内容等于完整的可滚动内容大小。我也尝试过根据单元格的数量计算它,但由于需要考虑 contentOffsets 和组间间距,我无法正确计算。

我的完整布局代码和结果 UI 的屏幕截图如下,以防万一。也许有一种方法可以更改此布局以达到相同的结果并在contentSize 中获得正确的值。

let layout: UICollectionViewLayout = {
    let itemWidth = itemSize.width - 2 * Const.margin
    let itemLayoutSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
    let item = NSCollectionLayoutItem(layoutSize: itemLayoutSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(itemWidth), heightDimension: .fractionalHeight(1.0))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

    let section = NSCollectionLayoutSection(group: group)
    section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: Const.margin, bottom: 0, trailing: Const.margin)
    section.interGroupSpacing = Const.interItemSpacing
    section.orthogonalScrollingBehavior = .groupPaging
    section.visibleItemsInvalidationHandler = { /* ... */ }

    return UICollectionViewCompositionalLayout(section: section)
}()

起始位置:

滚动到下一项:

【问题讨论】:

    标签: ios swift uicollectionview uicollectionviewlayout


    【解决方案1】:

    以防万一它对其他人有所帮助:这不是我希望的解决方案,但我最终想出了如何根据单元格数量计算内容宽度。对于我的布局,我唯一需要考虑的是组宽(与项目宽度相同)和组间间距:

    func contentWidth(forCellCount cellCount: Int) -> CGFloat {
        (itemWidth + Const.interItemSpacing) * CGFloat(cellCount)
    }
    

    请注意,我无权访问 visibleItemsInvalidationHandler 中的 cellCount,因此我必须(弱)在该闭包中捕获 self 并调用一个能够获取该值的方法:

    section.visibleItemsInvalidationHandler = { [weak self] _, scrollOffset, _ in
        self?.handleHorizontalScroll(scrollOffset: scrollOffset)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多