J'utilise UICollectionView
pour la première fois dans mon application iPad . J'ai défini UICollectionView
de sorte que sa taille et sa taille de cellule soient identiques, ce qui signifie qu'une seule cellule est affichée à la fois.
Problème: Maintenant, lorsque l'utilisateur fait défiler UICollectionView, j'ai besoin de savoir quelle cellule est visible, je dois mettre à jour d'autres éléments de l'interface utilisateur à la modification. Je n'ai trouvé aucune méthode de délégué pour cela. Comment puis-je atteindre cet objectif?
Code:
[self.mainImageCollection setTag:MAIN_IMAGE_COLLECTION_VIEW];
[self.mainImageCollection registerClass:[InspirationMainImageCollectionCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
[self.mainImageFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[self.mainImageFlowLayout setMinimumInteritemSpacing:0.0f];
[self.mainImageFlowLayout setMinimumLineSpacing:0.0f];
self.mainImageFlowLayout.minimumLineSpacing = 0;
[self.mainImageCollection setPagingEnabled:YES];
[self.mainImageCollection setShowsHorizontalScrollIndicator:NO];
[self.mainImageCollection setCollectionViewLayout:self.mainImageFlowLayout];
Ce que j'ai essayé:
Comme UICollectionView
Conforme à UIScrollView
, j'ai obtenu lorsque l'utilisateur scroll se termine avec la méthode UIScrollViewDelegate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
Mais à l'intérieur de la fonction ci-dessus, comment puis-je obtenir l'index de cellules visibles actuel de UICollectionView
???
La méthode [collectionView visibleCells] vous donne tout le tableau visibleCells que vous voulez. Utilisez-le quand vous voulez obtenir
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
NSLog(@"%@",indexPath);
}
}
indexPathsForVisibleItems
peut fonctionner dans la plupart des situations, mais parfois, il retourne un tableau avec plus d'un chemin d'index et il peut être difficile de déterminer celui que vous voulez. Dans ces situations, vous pouvez faire quelque chose comme ceci:
CGRect visibleRect = (CGRect){.Origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
Cela fonctionne particulièrement bien lorsque chaque élément de votre vue de collection occupe tout l'écran.
Version Swift
let visibleRect = CGRect(Origin: collectionView.contentOffset, size: collectionView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint)
Réponses de travail combinées dans Swift 2.2:
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = self.collectionView.contentOffset
visibleRect.size = self.collectionView.bounds.size
let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))
let visibleIndexPath: NSIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)
guard let indexPath = visibleIndexPath else { return }
print(indexPath)
}
Swift 3 & Swift 4 :
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = collectionView.contentOffset
visibleRect.size = collectionView.bounds.size
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
guard let indexPath = collectionView.indexPathForItem(at: visiblePoint) else { return }
print(indexPath)
}
Par souci d'exhaustivité, c'est la méthode qui a finalement fonctionné pour moi. C'était une combinaison des méthodes de @Anthony & @ iAn.
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
CGRect visibleRect = (CGRect){.Origin = self.collectionView.contentOffset, .size = self.collectionView.bounds.size};
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [self.collectionView indexPathForItemAtPoint:visiblePoint];
NSLog(@"%@",visibleIndexPath);
}
Il sera probablement préférable d'utiliser les méthodes UICollectionViewDelegate: (Swift 3)
// Called before the cell is displayed
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print(indexPath.row)
}
// Called when the cell is displayed
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
print(indexPath.row)
}
Je veux juste ajouter pour les autres: Pour une raison quelconque, je n’ai pas obtenu la cellule visible par l’utilisateur lorsque je faisais défiler jusqu’à la cellule previous dans collectionView avec pagingEnabled.
Donc, j'insère le code à l'intérieur de dispatch_async pour lui donner un peu d '"air" .__ et cela fonctionne pour moi.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
dispatch_async(dispatch_get_main_queue(), ^{
UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];
[visibleCell doSomthing];
});
}
Pour Swift 3.0
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let visibleRect = CGRect(Origin: colView.contentOffset, size: colView.bounds.size)
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
let indexPath = colView.indexPathForItem(at: visiblePoint)
}
Swift 3.0
La solution la plus simple qui vous donnera indexPath pour les cellules visibles.
yourCollectionView.indexPathsForVisibleItems
retournera le tableau de indexpath.
Prenez juste le premier objet du tableau comme ceci.
yourCollectionView.indexPathsForVisibleItems.first
Je suppose que cela devrait également bien fonctionner avec Objective - C.
var visibleCurrentCellIndexPath: IndexPath? {
for cell in self.collectionView.visibleCells {
let indexPath = self.collectionView.indexPath(for: cell)
return indexPath
}
return nil
}
Vous pouvez utiliser scrollViewDidEndDecelerating
: pour cela
//@property (strong, nonatomic) IBOutlet UICollectionView *collectionView;
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.collectionView visibleCells]) {
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
NSUInteger lastIndex = [indexPath indexAtPosition:[indexPath length] - 1];
NSLog(@"visible cell value %d",lastIndex);
}
}
convertir la réponse de @ Anthony en Swift 3.0 a parfaitement fonctionné pour moi:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.Origin = yourCollectionView.contentOffset
visibleRect.size = yourCollectionView.bounds.size
let visiblePoint = CGPoint(x: CGFloat(visibleRect.midX), y: CGFloat(visibleRect.midY))
let visibleIndexPath: IndexPath? = yourCollectionView.indexPathForItem(at: visiblePoint)
print("Visible cell's index is : \(visibleIndexPath?.row)!")
}
Vérifiez également cet extrait
let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)
C'est une vieille question mais dans mon cas ...
- (void) scrollViewWillBeginDragging:(UIScrollView *)scrollView {
_m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.firstObject].row;
}
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
_m_offsetIdx = [m_cv indexPathForCell:m_cv.visibleCells.lastObject].row;
}