当前位置:  开发笔记 > IOS > 正文

如何实现水平无限滚动UICollectionView?

如何解决《如何实现水平无限滚动UICollectionView?》经验,为你挑选了2个好方法。

我想实现UICollectionView水平和无限滚动?



1> cicerocamarg..:

如果您的数据是静态的并且您想要一种循环行为,则可以执行以下操作:

var dataSource = ["item 0", "item 1", "item 2"]

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return Int.max // instead of returnin dataSource.count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let itemToShow = dataSource[indexPath.row % dataSource.count]
    let cell = UICollectionViewCell() // setup cell with your item and return
    return cell
}

基本上你对你的集合视图说你有大量的单元格(Int.max不会是无限的,但可能会这样做),并且你使用%运算符访问你的数据源.在我的例子中,我们最终得到"项目0","项目1","项目2","项目0","项目1","项目2"....

我希望这有帮助 :)


返回`Int.max`崩溃模拟器:(
很优雅的解决方案 只是一个补充 - 如果你想让集合从头开始向左滚动,你可以使用:CollectionView.scrollToItem()并在初始化之后给它一些大的值.
你确定这不会引发性能问题吗?
@tarrball是的,但是单元格重用机制只能解决内存问题,如果单元格的大小取决于它显示的数据,并且您在`heightForRowAtIndexPath`或`sizeForItemAtIndexPath`中计算它们的大小/高度,这些方法将称为您的`numberOf .. InSection`返回的次数很多。我猜这可能会导致性能问题?即使我进行一些缓存,这里仍然会有数百万不必要的调用。
@tarrball,不!由于UITableView和UICollectionView是UIScrollView的子类,因此系统会在初始化滚动视图以确定其contentSize时计算每个单元格的大小,因此我尚未在实际应用中测试此方法,只是担心我可能会提出性能问题,也很高兴知道您已经实现了此功能,并且运行良好。
如果用户从一开始向左滑动会发生什么情况?会变成-1吗?

2> Bio-Matic..:

显然,最接近良好解决方案的是Manikanta Adimulam提出的.最干净的解决方案是在数据列表的开头添加最后一个元素,并将第一个元素添加到最后一个数据列表位置(例如:[4] [0] [1] [2] [3] [4] [ 0]),所以我们在触发最后一个列表项时滚动到第一个数组项,反之亦然.这适用于具有一个可见项的集合视图:

    子类UICollectionView.

    覆盖UICollectionViewDelegate并覆盖以下方法:

    public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let numberOfCells = items.count
        let page = Int(scrollView.contentOffset.x) / Int(cellWidth)
        if page == 0 { // we are within the fake last, so delegate real last
            currentPage = numberOfCells - 1
        } else if page == numberOfCells - 1 { // we are within the fake first, so delegate the real first
            currentPage = 0
        } else { // real page is always fake minus one
           currentPage = page - 1
        }
        // if you need to know changed position, you can delegate it
        customDelegate?.pageChanged(currentPage)
    }
    
    
    public func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let numberOfCells = items.count
        if numberOfCells == 1 {
            return
        }
        let regularContentOffset = cellWidth * CGFloat(numberOfCells - 2)
        if (scrollView.contentOffset.x >= cellWidth * CGFloat(numberOfCells - 1)) {
            scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x - regularContentOffset, y: 0.0)
        } else if (scrollView.contentOffset.x < cellWidth) {
            scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x + regularContentOffset, y: 0.0)
        }
    }
    

    覆盖UICollectionView中的layoutSubviews()方法,以便始终为第一个项目创建正确的偏移量:

    override func layoutSubviews() {
        super.layoutSubviews()
    
        let numberOfCells = items.count
        if numberOfCells > 1 {
            if contentOffset.x == 0.0 {
                contentOffset = CGPoint(x: cellWidth, y: 0.0)
            }
        }
    }
    

    覆盖init方法并计算单元格尺寸:

    let layout = self.collectionViewLayout as! UICollectionViewFlowLayout
    cellPadding = layout.minimumInteritemSpacing
    cellWidth = layout.itemSize.width
    

奇迹般有效!如果要在具有多个可见项的集合视图中实现此效果,请使用此处发布的解决方案.

推荐阅读
Gbom2402851125
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有