En étudiant les nouvelles fonctionnalités d'iOS6, j'ai eu une question sur ICollectionView .
Je le teste actuellement avec la disposition Flow et la direction de défilement définie sur horizontal, le défilement et la pagination étant activés. J'ai défini sa taille exactement comme les cellules de ma coutume, afin qu'elle puisse s'afficher une à la fois, et en la faisant défiler latéralement, l'utilisateur verrait les autres cellules existantes.
Cela fonctionne parfaitement.
Maintenant, je veux ajouter et IPageControl à la vue de collection que j'ai créée, afin qu'elle puisse montrer quelle cellule est visible et combien de cellules s'y trouvent.
La création du contrôle de page était plutôt simple, le cadre et numberOfPages définis.
Le problème que je rencontre, comme les points d'interrogation, est de savoir comment obtenir la cellule actuellement visible dans la vue de la collection, afin qu'elle puisse changer la page courante du contrôle de page.
J'ai essayé des méthodes déléguées, comme cellForItemAtIndexPath, mais il est fait pour charger des cellules, pas pour les afficher. didEndDisplayingCell se déclenche lorsqu'une cellule n'est plus affichée, l'événement inverse de ce dont j'ai besoin.
Il semble que -visibleCells et -indexPathsForVisibleItems, les méthodes d'affichage de collection, soient le bon choix pour moi, mais j'ai rencontré un autre problème. Quand les déclencher?
Merci d'avance, j'espère que je me suis fait assez clair pour que vous puissiez me comprendre!
Vous devez vous configurer en tant que UIScrollViewDelegate
et implémenter le scrollViewDidEndDecelerating:
méthode comme ceci:
Objectif-C
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = self.collectionView.contentOffset.x / pageWidth;
}
rapide
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageWidth = self.collectionView.frame.size.width
pageControl.currentPage = Int(self.collectionView.contentOffset.x / pageWidth)
}
J'ai également eu du mal avec cela pendant un certain temps, puis on m'a conseillé de vérifier les classes parentes d'UICollectionView. L'un d'eux se trouve être IScrollView et si vous vous configurez comme IScrollViewDelegate , vous avez accès à des méthodes très utiles telles que scrollViewDidEndDecelerating , un excellent endroit pour mettre à jour UIPageControl.
Je recommanderais un petit calcul et une manipulation optimisés car cela mettra à jour le contrôle de la page immédiatement dans n'importe quelle position de défilement avec une meilleure précision.
La solution ci-dessous fonctionne avec n'importe quelle vue de défilement ou sous-classe (UITableView UICollectionView et autres)
dans la méthode viewDidLoad, écrivez ceci
scrollView.delegate = self
puis utilisez le code de votre langue:
Swift 3
func scrollViewDidScroll(_ scrollView: UIScrollView)
{
let pageWidth = scrollView.frame.width
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
Swift 2:
func scrollViewDidScroll(scrollView: UIScrollView)
{
let pageWidth = CGRectGetWidth(scrollView.frame)
pageControl.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
}
Objectif c
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat pageWidth = self.collectionView.frame.size.width;
self.pageControl.currentPage = (self.collectionView.contentOffset.x + pageWidth / 2) / pageWidth;
}
Une autre option avec moins de code consiste à utiliser le chemin d'index des éléments visibles et à définir le contrôle de page.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
self.pageControl.currentPage = [[[self.collectionView indexPathsForVisibleItems] firstObject] row];
}
int pages = étage (ImageCollectionView.contentSize.width/ImageCollectionView.frame.size.width); [pageControl setNumberOfPages: pages];
Ajoutez la méthode ScrollView Delegate,
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
CGFloat pageWidth = ImageCollectionView.frame.size.width;
float currentPage = ImageCollectionView.contentOffset.x / pageWidth;
if (0.0f != fmodf(currentPage, 1.0f))
{
pageControl.currentPage = currentPage + 1;
}
else
{
pageControl.currentPage = currentPage;
}
NSLog(@"finishPage: %ld", (long)pageControl.currentPage);
}
Je sais que c'est une ancienne mais j'ai juste besoin d'implémenter à nouveau ce type de fonctionnalité et d'avoir un peu à ajouter qui donne une réponse plus complète.
Premièrement: L'utilisation de scrollViewDidEndDecelerating
suppose que l'utilisateur a levé son doigt tout en faisant glisser (plus comme une action de film) et qu'il y a donc une phase de décélération. Si l'utilisateur traîne sans lever le doigt, le UIPageControl
indiquera toujours l'ancienne page d'avant le début du glissement. Au lieu de cela, l'utilisation du rappel scrollViewDidScroll
signifie que la vue est mise à jour à la fois après le glisser-déplacer et également pendant le glisser-déplacer, ce qui la rend beaucoup plus réactive et précise pour l'utilisateur.
Deuxièmement: En se basant sur pagewidth
pour calculer l'index sélectionné, toutes les cellules ont la même largeur et il y a une cellule par écran. tirer parti de la méthode indexPathForItemAtPoint
sur UICollectionView
donne un résultat plus résilient qui fonctionnera pour différentes dispositions et tailles de cellule. L'implémentation ci-dessous suppose que le centre du cadre est la cellule souhaitée à représenter dans le pagecontrol
. De plus, s'il y a des espacements intercellulaires, il y aura des moments pendant le défilement lorsque le selectedIndex pourrait être nul ou facultatif, donc cela doit être vérifié et déballé avant de définir sur la pageControl.
func scrollViewDidScroll(scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset
let centrePoint = CGPointMake(
contentOffset.x + CGRectGetMidX(scrollView.frame),
contentOffset.y + CGRectGetMidY(scrollView.frame)
)
if let index = self.collectionView.indexPathForItemAtPoint(centrePoint){
self.pageControl.currentPage = index.row
}
}
Encore une chose - définissez le nombre de pages sur le UIPageControl
avec quelque chose comme ceci:
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
self.pageControl.numberOfPages = 20
return self.pageControl.numberOfPages
}
Simple Swift
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
pageControl.currentPage = (collectionView.indexPathsForVisibleItems().first?.row)!
}
UIScrollViewDelegate
est déjà implémenté si vous implémentez UICollectionViewDelegate