web-dev-qa-db-fra.com

Détection du changement de page UIScrollView

Existe-t-il un moyen de détecter ou d'obtenir une notification lorsque l'utilisateur change de page dans un UIScrollView activé pour la pagination

74
Pompair

Implémentez le délégué de UIScrollView. This méthode est ce que vous recherchez.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
18
Viraj

Utilisez cette option pour détecter la page actuellement affichée et effectuer certaines actions lors du changement de page:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    static NSInteger previousPage = 0;
    CGFloat pageWidth = scrollView.frame.size.width;
    float fractionalPage = scrollView.contentOffset.x / pageWidth;
    NSInteger page = lround(fractionalPage);
    if (previousPage != page) {
        // Page has changed, do your thing!
        // ...
        // Finally, update previous page
        previousPage = page;
    }
}

S'il est acceptable que vous réagissiez au changement de page une fois le défilement complètement arrêté, il serait alors préférable de procéder comme indiqué ci-dessus dans la méthode déléguée scrollViewDidEndDecelerating: au lieu de la méthode scrollViewDidScroll:.

191
Michael Waterfall

Dans la vue de défilement activée pour la pagination, vous pouvez utiliser scrollViewDidEndDecelerating pour savoir quand la vue est réglée sur une page (peut-être la même page). 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

scrollViewDidScroll est appelé à chaque mouvement. Et dans le contexte de la pagination activée, la vue peut être utilisée pour déterminer quand le défilement est suffisant pour passer à la page suivante (si le glissement est arrêté à cet endroit).

62
Ankur Badola

Pourquoi ne pas combiner deux méthodes de UIScrollViewDelegate?

Dans scrollViewDidEndDragging(_:willDecelerate:), s’il s’arrête immédiatement, nous calculons la page; si elle décélère, nous la laissons aller et elle sera interceptée par scrollViewDidEndDecelerating(_:).

Le code est testé avec XCode version 7.1.1, Swift version 2.1

class ViewController: UIViewController, UIScrollViewDelegate {

  // MARK: UIScrollViewDelegate
  func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
    if decelerate == false {
        let currentPage = scrollView.currentPage
        // Do something with your page update
        print("scrollViewDidEndDragging: \(currentPage)")
    }
  }

  func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
    let currentPage = scrollView.currentPage
    // Do something with your page update
    print("scrollViewDidEndDecelerating: \(currentPage)")
  }

}

extension UIScrollView {
   var currentPage: Int {
      return Int((self.contentOffset.x+ (0.5*self.frame.size.width))/self.frame.width)+1
   }
}
31
Cullen SUN

Premier résultat sur Google pour la détection de page, je devais donc y répondre avec une meilleure solution à mon avis. (Même si cette question a été posée il y a 2 ans et demi.)

Je préférerais ne pas appeler scrollViewDidScroll uniquement pour suivre le numéro de page. C’est exagéré pour quelque chose d'aussi simple que ça .. Utiliser scrollViewDidEndDecelerating fonctionne et s'arrête lors d'un changement de pageMAIS(et c'est un gros mais) si l'utilisateur balaie l'écran deux fois un peu plus vite que la normale scrollViewDidEndDecelerating sera appelé une seule fois. Vous pouvez facilement aller de la page 1 à la page 3 sans traiter la page 2.

Cela l'a résolu complètement pour moi:

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{
    scrollView.userInteractionEnabled = NO;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //Run your code on the current page
    scrollView.userInteractionEnabled = YES;
}

De cette façon, l'utilisateur ne peut glisser qu'une page à la fois sans le risque décrit ci-dessus.

21
Segev

Swift 4

J'ai trouvé la meilleure façon de faire est d'utiliser scrollViewWillEndDragging(_:withVelocity:targetContentOffset:). Il vous permet de prédire si la pagination se produira dès que vous retirez votre doigt de l'écran. Cet exemple concerne la pagination horizontale.

N'oubliez pas d'assigner le scrollView.delegate à l'objet qui adopte UIScrollViewDelegate et implémente cette méthode.

var previousPageXOffset: CGFloat = 0.0

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

    let targetOffset = targetContentOffset.pointee

    if targetOffset.x == previousPageXOffset {
        // page will not change
    } else if targetOffset.x < previousPageXOffset {
        // scroll view will page left
    } else if targetOffset.x > previousPageXOffset {
        // scroll view will page right
    }

    previousPageXOffset = targetOffset.x
    // If you want to track the index of the page you are on just just divide the previousPageXOffset by the scrollView width.
    // let index = Int(previousPageXOffset / scrollView.frame.width)


}
8
Doug Galante

Voici la solution Swift pour cela.

Faites deux propriétés currentPage et previousPage dans la classe où vous implémentez votre code et initialisez-les à 0.

Maintenant, mettez à jour currentPage depuis scrollViewDidEndDragging (: willDecelerate:) Et scrollViewDidEndDecelerating (: scrollView :).

Et puis mettez à jour previousPage dans scrollViewDidEndScrollingAnimation (_: scrollView :)

    //Class Properties
    var currentPage = 0
    var previousPage = 0

func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        updatePage(scrollView)
        return
    }

 func scrollViewDidEndDecelerating(scrollView: UIScrollView){
        updatePage(scrollView)
        return
    }


 func updatePage(scrollView: UIScrollView) {
        let pageWidth:CGFloat = scrollView.frame.width
        let current:CGFloat = floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1
        currentPage = Int(current)

        if currentPage == 0 {
              // DO SOMETHING
        }
        else if currentPage == 1{
              // DO SOMETHING

        }
    }

func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
     if previousPage != currentPage {
          previousPage = currentPage
          if currentPage == 0 {
              //DO SOMETHING
             }else if currentPage == 1 {
               // DO SOMETHING
           }
       }
   }
1
Rohit tomar

Pour Swift

static var previousPage: Int = 0
func scrollViewDidScroll(_ scrollView: UIScrollView){
let pageWidth: CGFloat = scrollView.frame.width
let fractionalPage: CGFloat = scrollView.contentOffset.x / pageWidth
let page = lround(Double(fractionalPage))
if page != previousPage
{
  print(page)
  // page changed
}
}
0
Hiren Panchal