web-dev-qa-db-fra.com

Comment ajouter PageControl dans UICollectionView Image Scrolling

Bonjour, j'ai UICollectionView codes de listage d'images horizontales que je veux ajouter PageControl lorsque le défilement des images s'affiche, j'ai ajouté le sélecteur pagecontrol et IBOutlet mais comment puis-je l'intégrer? entre UICollecitonView. ?

Mes codes ci-dessous.

 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.
    }



}
22
SwiftDeveloper

Vous avez ici une classe complète avec la pagination du contrôle de page dans une vue de collection horizontale. Cela fonctionne sur l'une de mes applications, en ce moment, et fonctionne correctement. Si vous ne pouvez pas le faire fonctionner, n'hésitez pas à me demander et je vous aiderai.

Tout d’abord, dans le Storyboard, vous devez configurer votre CollectionView avec:

Mise en page: Débit
Sens du défilement: Horizontal
Défilement activé
pagination activée

@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)
}
39
Juan Curti

Je ne suis pas fan de la réponse acceptée. De temps en temps, willDisplay cell retournera la mauvaise page pour le contrôle de page en fonction de l'interaction des utilisateurs.

Ce que j'utilise:

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

Ceci mettra à jour la page une fois que l'utilisateur aura fini de faire défiler le texte, rendant ainsi le currentPage du pageControl plus précis.

84
luke

Pour un contrôle UIPage plus réactif, je préfère utiliser scrollViewDidScroll et calculer le décalage par rapport au centre horizontal de la propriété 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)
}
25
David Baez

Si vous attendez scrollViewDidEndDecelerating, la mise à jour de UIPageControl sera lente. Si vous voulez une interface utilisateur plus réactive, je suggère plutôt de mettre en œuvre scrollViewWillEndDragging(_:withVelocity:targetContentOffset:) .

Exemple de Swift 4 où chaque section de vue de collection est une page:

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
    }
}
11
Chris Chute

La réponse de Luke était un bon début pour moi mais il y avait deux problèmes: il ne mettait pas à jour fréquemment (déjà noté dans d'autres réponses) mais surtout, il ne montrait pas la page correcte pour le dernier élément de ma collection vue (orientée horizontalement) et il a seulement changé de page lorsque l'élément a été presque quitter l'écran.

Comme d'autres l'ont fait remarquer, pour le premier numéro, utiliser scrollViewDidScroll offrait une meilleure expérience. J'étais préoccupé par les problèmes de performances liés à la fréquence de l'appel, mais je n'en ai pas remarqué.

En ce qui concerne le deuxième problème, pour mon cas d'utilisation, trouver le chemin indexPath de la cellule située au centre de l'écran constituait une meilleure solution. N'oubliez pas que si votre cas d'utilisation peut contenir plus de deux cellules à l'écran, il peut être nécessaire de l'ajuster. En effet, votre dernière cellule n’atteindrait jamais le milieu de l’écran. Je dirais cependant que dans ce cas, utiliser UIPageControl pourrait ne pas être idéal de toute façon.

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
    }
}
5
lbarbosa

Swift 5 Très bon travail

//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
    }
}
4
Shakeel Ahmed
 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
        }
    }
3