ios 如何在 UICollectionView 图像滚动中添加 PageControl

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40975302/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:53:57  来源:igfitidea点击:

How to add PageControl inside UICollectionView Image Scrolling

iosswiftuicollectionviewswift3uipagecontrol

提问by SwiftDeveloper

I have UICollectionViewHorizontal Image listing codes. I want to add PageControlwhen scrolling images will shows, I added pagecontrol selector and IBOutletbut how can I integrate it between UICollecitonView?

我有UICollectionView水平图像列表代码。我想PageControl在滚动图像显示时添加,我添加了页面控件选择器,IBOutlet但如何在它们之间集成UICollecitonView

My codes are below:

我的代码如下:

 class  ViewController: UIViewController,  UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {


    @IBOutlet weak var View : DesignableView!


    @IBOutlet var collectionView: UICollectionView!
    @IBOutlet var collectionViewLayout: UICollectionViewFlowLayout!

    @IBOutlet open weak var pageControl: UIPageControl? {
        didSet {
            pageControl?.addTarget(self, action: #selector(ViewController.pageChanged(_:)), for: .valueChanged)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

         pageControl?.numberOfPages = 11


    }


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




    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: ImageCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCollectionViewCell", for: indexPath) as! ImageCollectionViewCell
        cell.label.text = "Cell \(indexPath.row)"
        cell.backgroundImageView.image = UIImage(named: "Parallax \(indexPath.row + 1)")

        // Parallax cell setup
        cell.parallaxTheImageViewScrollOffset(self.collectionView.contentOffset, scrollDirection: self.collectionViewLayout.scrollDirection)
        return cell
    }



    @IBAction open func pageChanged(_ sender: UIPageControl) {

        print(sender.currentPage)


    }




    // MARK: Delegate

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return collectionView.bounds.size;
    }

    // MARK: Scrolling

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // Parallax visible cells
        for cell: ImageCollectionViewCell in collectionView.visibleCells as! [ImageCollectionViewCell] {
            cell.parallaxTheImageViewScrollOffset(self.collectionView.contentOffset, scrollDirection: self.collectionViewLayout.scrollDirection)
        }
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }



}

回答by luke

I'm not a fan of the accepted answer. From time to time, willDisplay cellwill return the wrong page for the page control depending on users interaction.

我不喜欢接受的答案。willDisplay cell根据用户交互,有时会为页面控件返回错误的页面。

What I use:

我使用的是:

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

This will update the page after the user has finished scrolling thus making the currentPageof the pageControlmore accurate.

这将在用户完成滚动后更新页面,从而使currentPagepageControl更准确。

回答by Juan Curti

Here you have a complete class with Page Control pagination in a horizontal collection view. This is working on one of my applications, right now, and is working correctly. If you cannot get it work, do feel free to ask me and I'll help you.

在这里,您有一个完整的类,其中包含水平集合视图中的 Page Control 分页。这正在我的一个应用程序上工作,现在,并且工作正常。如果你不能让它工作,请随时问我,我会帮助你。

First, in the Storyboard you have to set up your CollectionView with:

首先,在 Storyboard 中,您必须使用以下命令设置 CollectionView:

Layout: Flow
Scroll Direction: Horizontal
Scrolling enabled
Paging enabled

布局:流
滚动方向
启用水平滚动启用
分页

@IBOutlet weak var collectionView: UICollectionView! //img: 77

@IBOutlet weak var pageControl: UIPageControl!

var thisWidth:CGFloat = 0

override func awakeFromNib() {
    super.awakeFromNib()

    thisWidth = CGFloat(self.frame.width)
    collectionView.delegate = self
    collectionView.dataSource = self

    pageControl.hidesForSinglePage = true

}

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 10
}

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "YourCell", for: indexPath)

    return cell
}

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    self.pageControl.currentPage = indexPath.section
}

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

回答by David Baez

For a more responsive UIPageControl, I prefer to use scrollViewDidScrolland calculating the offset with regards to the horizontal center of the scrollView.

对于响应更快的 UIPageControl,我更喜欢使用scrollViewDidScroll和计算关于 scrollView 的水平中心的偏移量。

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offSet = scrollView.contentOffset.x
    let width = scrollView.frame.width
    let horizontalCenter = width / 2

    pageControl.currentPage = Int(offSet + horizontalCenter) / Int(width)
}

回答by Chris Chute

Waiting for scrollViewDidEndDeceleratingresults in a slow update to the UIPageControl. If you want a more responsive UI, I suggest instead implementing scrollViewWillEndDragging(_:withVelocity:targetContentOffset:).

等待scrollViewDidEndDecelerating结果会导致UIPageControl. 如果你想要一个响应更快的用户界面,我建议改为实现scrollViewWillEndDragging(_:withVelocity:targetContentOffset:).

Swift 4 example where each collection view section is a page:

Swift 4 示例,其中每个集合视图部分都是一个页面:

override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    if let collectionView = scrollView as? ScoreCollectionView,
        let section = collectionView.indexPathForItem(at: targetContentOffset.pointee)?.section {
        self.pageControl.currentPage = section
    }
}

回答by Shakeel Ahmed

Swift 5 Very Smooth working

Swift 5 非常流畅的工作

//MARK:- For Display the page number in page controll of collection view Cell
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: self.collectionview.contentOffset, size: self.collectionview.bounds.size)
    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
    if let visibleIndexPath = self.collectionview.indexPathForItem(at: visiblePoint) {
        self.pageControl.currentPage = visibleIndexPath.row
    }
}

回答by lbarbosa

Luke's answerwas a good start for me but it had two issues: it didn't update frequently (already noted in other answers) but most importantly it didn't show the correct page for the last item in my collection view (horizontally oriented) and it only switched page when the item was almost leaving the screen.

Luke 的回答对我来说是一个好的开始,但它有两个问题:它没有经常更新(已经在其他答案中指出)但最重要的是它没有显示我收藏视图中最后一个项目的正确页面(水平方向)它只在项目几乎离开屏幕时才切换页面。

For the first issue, as others noted, using scrollViewDidScrollprovided a better experience. I was concerned about performance issues for making the call so frequently but didn't notice any.

对于第一个问题,正如其他人指出的那样,使用scrollViewDidScroll提供了更好的体验。我担心如此频繁地拨打电话的性能问题,但没有注意到任何问题。

As for the second issue, for my use case, finding the indexPath of the cell that is at the center of the screen provided a better solution. Keep in mind that if your use case can fit more than two cells on screen this may need to be adjusted. This is because your last cell would never reach the middle of the screen. I would argue though that in that case using the UIPageControlmight not be ideal anyway.

至于第二个问题,对于我的用例,找到位于屏幕中心的单元格的 indexPath 提供了更好的解决方案。请记住,如果您的用例可以在屏幕上容纳两个以上的单元格,则可能需要进行调整。这是因为您的最后一个单元格永远不会到达屏幕中间。我会争辩说,在那种情况下使用UIPageControl可能并不理想。

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
    let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
    if let visibleIndexPath = self.collectionView.indexPathForItem(at: visiblePoint) {
        self.pageControl.currentPage = visibleIndexPath.row
    }
}

回答by Davender Verma

 func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let visibleRect = CGRect(origin: self.cvImageListing.contentOffset, size: self.cvImageListing.bounds.size)
        let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
        if let visibleIndexPath = self.cvImageListing.indexPathForItem(at: visiblePoint) {
            self.pageControl.currentPage = visibleIndexPath.row
        }
    }

回答by Rahul Gusain

swift 5 example:

快速 5 示例:

function to set pageController CurrentPage according to Index of CollectionView:

根据 CollectionView 的索引设置 pageController CurrentPage 的函数:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
   let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
   let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
   if let visibleIndexPath = self.collectionView.indexPathForItem(at: visiblePoint) {
            self.pageController.currentPage = visibleIndexPath.row
   }
}

PageControllerAction function to scroll CollectionView on selecting PageController :

PageControllerAction 函数在选择 PageController 时滚动 CollectionView :

@IBAction func pageControllerAction(_ sender: UIPageControl) {
       self.collectionView.scrollToItem(at: IndexPath(row: sender.currentPage, section: 0), at: .centeredHorizontally, animated: true)
}

回答by Khushtar parvez

Simply add this function

只需添加此功能

func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView){
    //Test the offset and calculate the current page after scrolling ends
    let pageWidth:CGFloat = scrollView.frame.width
    let currentPage:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1
    //Change the indicator
    self.pageControl.currentPage = Int(currentPage);
}