如何实现UIPageControl与UICollectionView内部scrollView的联动?
解决方案
你需要先明确你的UIPageControl对应的是哪一层滚动的页码,两种场景的实现方式如下:
场景1:PageControl对应CollectionView的cell切换页码(即3个cell对应3个页码)
这种是最常见的用法,你已经给CollectionView设置了整页横向滚动,直接关联CollectionView的滚动事件即可:
- 补充
scrollViewDidScroll实现,监听CollectionView滚动更新页码:
func scrollViewDidScroll(_ scrollView: UIScrollView) { // 区分是CollectionView滚动还是cell内部的scrollView滚动 guard scrollView == collectionView else { return } let currentPage = Int(round(scrollView.contentOffset.x / scrollView.frame.width)) pageControl.currentPage = currentPage }
- 实现PageControl点击事件,点击时让CollectionView滚动到对应cell:
@objc func pageControlTapHandler(sender: UIPageControl) { let targetIndexPath = IndexPath(item: sender.currentPage, section: 0) collectionView.scrollToItem(at: targetIndexPath, at: .centeredHorizontally, animated: true) }
场景2:PageControl对应cell内部scrollView的3张图片切换页码
你需要通过代理把cell内部scrollView的滚动事件回传到ViewController更新PageControl:
- 给
DayWeatherCell添加代理协议,回调页码变化:
在DayWeatherCell类的上方定义协议:
protocol DayWeatherCellDelegate: AnyObject { func cell(_ cell: DayWeatherCell, didChangeImagePage page: Int) }
给DayWeatherCell添加代理属性,同时实现scrollView代理方法计算当前页码:
class DayWeatherCell: UICollectionViewCell, UIScrollViewDelegate { weak var delegate: DayWeatherCellDelegate? // 原有代码保持不变 func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { let currentPage = Int(scrollView.contentOffset.x / scrollView.frame.width) delegate?.cell(self, didChangeImagePage: currentPage) } }
注意:你当前的代码里还没有把3个imageView添加到cell的scrollView中,也没有设置scrollView的contentSize为3倍自身宽度,需要补充这部分逻辑才能正常滚动。
- 在ViewController中遵守代理协议,接收回调更新PageControl:
首先在cellForItemAt中设置cell的代理:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "sliderCell", for: indexPath) as! DayWeatherCell cell.delegate = self pageControl.numberOfPages = 3 // 对应cell内的3张图片 cell.backgroundColor = .red return cell }
实现代理方法更新页码:
extension MainScrenenViewController: DayWeatherCellDelegate { func cell(_ cell: DayWeatherCell, didChangeImagePage page: Int) { pageControl.currentPage = page } }
- 实现PageControl点击事件,让当前显示的cell滚动到对应图片页:
@objc func pageControlTapHandler(sender: UIPageControl) { guard let currentVisibleCell = collectionView.visibleCells.first as? DayWeatherCell else { return } let targetOffsetX = CGFloat(sender.currentPage) * currentVisibleCell.scrollView.frame.width currentVisibleCell.scrollView.setContentOffset(CGPoint(x: targetOffsetX, y: 0), animated: true) }
内容的提问来源于stack exchange,提问作者Mikl.hart
相关产品推荐
相关产品推荐

