Swift 带有UIPageControl的无限UICollectionview

Swift 带有UIPageControl的无限UICollectionview,swift,uicollectionview,swift4,infinite-scroll,uipagecontrol,Swift,Uicollectionview,Swift4,Infinite Scroll,Uipagecontrol,在下面给出的代码中,我可以简单地无限滚动单元格。至少在向前滚动(屏幕右侧)时,页面控件似乎也在工作。但坦率地说,当我向左滚动时,我看到3个项目的奇怪索引路径跳转(顺便说一下,我的数据源有3个项目用于测试)。在屏幕上我没有发现任何错误。但页面控件似乎暂时停止工作,并再次开始工作,但发生了一次移位,并为单元格显示了错误的点。有什么想法吗?谢谢你的帮助 import UIKit class HomeHeaderCell: CategoryCell { private let cellId

在下面给出的代码中,我可以简单地无限滚动单元格。至少在向前滚动(屏幕右侧)时,页面控件似乎也在工作。但坦率地说,当我向左滚动时,我看到3个项目的奇怪索引路径跳转(顺便说一下,我的数据源有3个项目用于测试)。在屏幕上我没有发现任何错误。但页面控件似乎暂时停止工作,并再次开始工作,但发生了一次移位,并为单元格显示了错误的点。有什么想法吗?谢谢你的帮助

import UIKit

class HomeHeaderCell: CategoryCell {

    private let cellId = "cellId"
    private var timer: Timer?
    private let infiniteSize = 1000
    private var onlyOnce = true

    // ...

    let pageControl: UIPageControl = {
        let rect = CGRect(origin: .zero, size: CGSize(width: 200, height: 50))
        let pc = UIPageControl(frame: rect)
        pc.currentPage = 0
        pc.numberOfPages = 3
        pc.pageIndicatorTintColor = .gray
        pc.currentPageIndicatorTintColor = .red
        pc.isUserInteractionEnabled = false
        return pc
    }()

    override func setupViews() {

        addSubview(baseCollectionView)
        addSubview(pageControl)


        baseCollectionView.delegate = self
        baseCollectionView.dataSource = self
        baseCollectionView.register(HeaderCell.self, forCellWithReuseIdentifier: cellId)

        baseCollectionView.backgroundColor = .white
        baseCollectionView.isPagingEnabled = true
        baseCollectionView.isScrollEnabled = true

        baseCollectionView.showsHorizontalScrollIndicator = false


        baseCollectionView.anchor(top: topAnchor, leading: leadingAnchor, bottom: bottomAnchor, trailing: trailingAnchor)
        pageControl.anchor(top: nil, leading: leadingAnchor, bottom: bottomAnchor, trailing: nil, padding: UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 0))
    }


    @objc func autoScroll() {
        guard let currentItemNumber = baseCollectionView.indexPathsForVisibleItems.first?.item  else { return }
        let nextItemNumber = currentItemNumber + 1
        let nextIndexPath = IndexPath(item: nextItemNumber, section: 0)
        baseCollectionView.scrollToItem(at: nextIndexPath, at: .left, animated: true)
    }

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        stopTimer()
    }
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        startTimer()
    }

    func startTimer() {
        timer = Timer.scheduledTimer(timeInterval: 4.0, target: self, selector: #selector(autoScroll), userInfo: nil, repeats: true)
    }

    func stopTimer() {
        timer?.invalidate()
        timer = nil
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return infiniteSize
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! HeaderCell

        // Maybe can be done more elegantly...
        if let foods = foodCategory?.foods {
            let numberOfFood = indexPath.item % foods.count
            cell.food = foods[numberOfFood]
            pageControl.currentPage = numberOfFood
            print(numberOfFood)
        }
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if onlyOnce  {
            let middleIndex = IndexPath(item: Int (infiniteSize / 2), section: 0)
            baseCollectionView.scrollToItem(at: middleIndex, at: .centeredHorizontally, animated: false)
            startTimer()
            onlyOnce = false
        }
    }

    override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: frame.width, height: frame.height)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    private class HeaderCell: ItemCell {

        override func setupViews() {
            addSubview(imageView)

            imageView.layer.cornerRadius = 0
            imageView.layer.borderColor = UIColor(white: 0.5, alpha: 0.5).cgColor
            imageView.layer.borderWidth = 0.5

            imageView.anchor(top: topAnchor, leading: leadingAnchor, bottom: bottomAnchor, trailing: trailingAnchor)
        }
    }

}
导入UIKit
类HomeHeaderCell:类别Cell{
private let cellId=“cellId”
私有变量计时器:计时器?
私有let无穷小=1000
私有变量onlyOnce=true
// ...
让pageControl:UIPageControl={
设rect=CGRect(原点:.0,大小:CGSize(宽:200,高:50))
设pc=UIPageControl(帧:rect)
pc.currentPage=0
pc.numberOfPages=3
pc.pageIndicatorTintColor=.gray
pc.currentPageIndicatorTintColor=.red
pc.isUserInteractionEnabled=false
返回pc
}()
覆盖函数设置视图(){
addSubview(baseCollectionView)
addSubview(页面控件)
baseCollectionView.delegate=self
baseCollectionView.dataSource=self
baseCollectionView.register(HeaderCell.self,forCellWithReuseIdentifier:cellId)
baseCollectionView.backgroundColor=.white
baseCollectionView.isPaginEnabled=true
baseCollectionView.IsCrollenabled=true
baseCollectionView.showshorizontalscrolindicator=false
baseCollectionView.anchor(顶部:顶部锚定,引导:引导锚定,底部:底部锚定,尾随:拖曳锚定)
pageControl.anchor(顶部:零,前导:前导anchor,底部:底部anchor,尾部:零,填充:UIEdgeInsets(顶部:0,左侧:16,底部:0,右侧:0))
}
@objc func autoScroll(){
guard let currentItemNumber=baseCollectionView.indexPathsForVisibleItems.first?.item else{return}
让nextItemNumber=currentItemNumber+1
让nextIndexPath=IndexPath(项:nextItemNumber,节:0)
baseCollectionView.scrollToItem(位于:nextIndexPath,位于:。左侧,动画:true)
}
func scrollView将开始刷新(scrollView:UIScrollView){
停止计时器()
}
func ScrollViewWillendDraging(scrollView:UIScrollView,withVelocity:CGPoint,targetContentOffset:UnsafemeutablePointer){
startTimer()
}
func startTimer(){
timer=timer.scheduledTimer(时间间隔:4.0,目标:self,选择器:#选择器(autoScroll),userInfo:nil,repeats:true)
}
函数停止计时器(){
计时器?.invalidate()
计时器=零
}
重写func collectionView(collectionView:UICollectionView,numberOfItemsInSection:Int)->Int{
返回无穷小
}
重写func collectionView(collectionView:UICollectionView,cellForItemAt indexPath:indexPath)->UICollectionViewCell{
让cell=collectionView.dequeueReusableCell(withReuseIdentifier:cellId,for:indexPath)作为!HeaderCell
//也许可以做得更优雅些。。。
如果let foods=食品类别?食品{
让numberofood=indexPath.item%foods.count
cell.food=食物[numberOfFood]
pageControl.currentPage=numberOfFood
打印(食品编号)
}
返回单元
}
func collectionView(collectionView:UICollectionView,willDisplay单元格:UICollectionViewCell,forItemAt indexPath:indexPath){
只要{
让middleIndex=IndexPath(项:Int(无穷大/2),节:0)
baseCollectionView.scrollToItem(位于:中间索引,位于:。中心水平,动画:false)
startTimer()
onlyOnce=false
}
}
重写func collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,sizeForItemAt indexPath:indexPath)->CGSize{
返回CGSize(宽度:frame.width,高度:frame.height)
}
func collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,MinimumLineSpacingforSection:Int)->CGFloat{
返回0
}
私有类HeaderCell:ItemCell{
覆盖函数设置视图(){
添加子视图(图像视图)
imageView.layer.cornerRadius=0
imageView.layer.borderColor=UIColor(白色:0.5,alpha:0.5)。cgColor
imageView.layer.borderWidth=0.5
imageView.anchor(顶部:顶部锚定,引导:引导锚定,底部:底部锚定,尾随:拖曳锚定)
}
}
}

我解决了自己的问题。以下是您应该应用的代码。前两个方法是UICrollView方法,UICollectionView免费提供,它是UICrollView的一个子类。updatePageControl方法是我为保持代码干净和简单而编写的方法。希望这有助于

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
    updatePageControl(scrollView: scrollView)
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    updatePageControl(scrollView: scrollView)
}
func updatePageControl(scrollView: UIScrollView) {
    let pageNumber = round(scrollView.contentOffset.x / scrollView.bounds.size.width)
    guard let count = foodCategory?.foods?.count else {return}
    let currentPageNumber = Int(pageNumber) % count
    pageControl.currentPage = currentPageNumber
}

我解决了自己的问题。以下是您应该应用的代码。前两个方法是UICrollView方法,UICollectionView免费提供,它是UICrollView的一个子类。updatePageControl方法是我为保持代码干净和简单而编写的方法。希望这有助于

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
    updatePageControl(scrollView: scrollView)
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    updatePageControl(scrollView: scrollView)
}
func updatePageControl(scrollView: UIScrollView) {
    let pageNumber = round(scrollView.contentOffset.x / scrollView.bounds.size.width)
    guard let count = foodCategory?.foods?.count else {return}
    let currentPageNumber = Int(pageNumber) % count
    pageControl.currentPage = currentPageNumber
}

你能把代码缩减到只显示与问题相关的位吗。就像在设置页面控件值时一样。有太多的代码要过滤。请使用FSPagerView pod。您可以减少代码以仅显示与问题相关的位。就像在设置页面控件值时一样。代码太多,无法通过它进行筛选。请使用FSPagerView pod