【问题标题】:How to connect UIPageControl to UICollectionView (Swift)如何将 UIPageControl 连接到 UICollectionView (Swift)
【发布时间】:2017-12-11 03:11:48
【问题描述】:

我目前正在使用 UICollectionView 来显示 3 张图像(每张图像跨越整个单元格)。我还有一个放置在 UICollectionView 顶部的 UIPageControl。我想要发生的是让 UIPageControl 显示图像的数量(在本例中为 3),以及用户当前正在查看的图像。我想要达到的效果是 Instagram 应用程序的效果。

我目前用来实现这种效果的方法是将 UIPageControl 的更新放在 UICollectionView 的 willDisplay 函数中,如下所示:

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    pictureDots.currentPage = indexPath.item
}

这可以正确连接集合视图和页面控件之间的分页效果。但是,我遇到的问题是 UIPageControl 开始说用户在第三张图像上,即使它正在显示第一张图像。

有谁知道为什么会发生这种情况以及如何解决这个问题?

【问题讨论】:

    标签: ios swift uicollectionview uipagecontrol


    【解决方案1】:

    首先将您的UIPageControl 与您的UICollectionView 添加到您的故事板中,然后将它们作为插座连接到您的视图控制器。

    @IBOutlet var pageControl: UIPageControl!
    @IBOutlet var collectionView: UICollectionView!
    

    调整UICollectionViewDataSource 中的numberOfItemsInSection 方法,将页面控件的计数设置为始终等于集合视图中的单元格数。

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
        let count = ...
    
        pageControl.numberOfPages = count
        pageControl.isHidden = !(count > 1)
    
        return count
    }
    

    最后,使用UIScrollViewDelegate,我们可以知道UICollectionView 停在哪个单元格上。如果您没有使用UICollectionViewController,您可能需要添加委托协议。

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    
        pageControl?.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
    
        pageControl?.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
    }
    

    这是可能的,因为 UICollectionView 实际上是 UIScrollView

    【讨论】:

    • 可以有n页的情况下如何决定页数?
    • @Hemang 页面数应该等于集合视图中的项目数。在numberOfItemsInSection 中,您通常会返回数据源中元素的数量。此处截取编号为count,并设置页数。
    • 在我的例子中,我有一个固定大小的集合视图,它将在一列中显示 5 行。因此,假设有 20 条记录,它将显示 4 列,每列 5 行。所以我需要的是获得 4 运行时。
    • 如果 Collection 视图位于 TableView 单元格内,这会起作用吗?并且集合视图数据源和委托是 ViewController 类,它包含 TableView 而不是 TableViewcell 类
    【解决方案2】:

    第 1 步为 Collection View 和 Page Control 创建变量

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet var pageControl:UIPageControl!     
    

    第二步设置Page Control的页数

    override func viewDidLoad() {
        super.viewDidLoad()         
        self.pageControl.numberOfPages = procedures.count
        //Set the delegate
        self.collectionView.delegate = self
    }
    

    *Step 3在scrollViewDidScroll函数中计算集合单元格的宽度和当前页面的索引。

        extension YourCollectionVC: UICollectionViewDataSource, UICollectionViewDelegate {
                override func scrollViewDidScroll(_ scrollView: UIScrollView) {
                    let witdh = scrollView.frame.width - (scrollView.contentInset.left*2)
                    let index = scrollView.contentOffset.x / witdh
                    let roundedIndex = round(index)
                    self.pageControl?.currentPage = Int(roundedIndex)
                }
    }
    

    注意:这个是水平显示的集合视图,垂直方向改变方法。

    在 swift 4 中测试。

    【讨论】:

      【解决方案3】:

      使用它来顺利运行。

       func scrollViewDidScroll(_ scrollView: UIScrollView) {
          let witdh = scrollView.frame.width - (scrollView.contentInset.left*2)
          let index = scrollView.contentOffset.x / witdh
          let roundedIndex = round(index)
          self.pageControl.currentPage = Int(roundedIndex)
      }
      func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
      
          pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
      }
      
      func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
      
          pageControl.currentPage = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
      }
      

      【讨论】:

        【解决方案4】:

        借助Combine,我们可以轻松地将UIPageControl 与任何ScrollView 连接起来。

        var collectionView: UICollectionView
        var bin: Set<AnyCancellable> = []
        var pageControl: UIPageControl
        
        // setup observer
        collectionView
            .publisher(for: \.contentOffset)
            .map { [unowned self] offset in
                Int(round(offset.x / max(1, self.collectionView.bounds.width)))
            }
            .removeDuplicates()
            .assign(to: \.currentPage, on: pageControl) // may cause memory leak use sink
            .store(in: &bin)
        

        【讨论】:

          猜你喜欢
          • 2022-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-23
          • 2014-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多