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
Implémentez le délégué de UIScrollView. This méthode est ce que vous recherchez.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
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:
.
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).
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
}
}
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.
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)
}
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
}
}
}
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
}
}