ios - UICollectionView índice de celda visible actual
objective-c ipad (14)
Estoy usando UICollectionView
primera vez en mi aplicación de iPad. He configurado UICollectionView
modo que su tamaño y tamaño de celda sean los mismos, significa que solo se muestra una celda a la vez.
Problema: Ahora, cuando el usuario se desplace UICollectionView, necesito saber qué celda está visible, tengo que actualizar otros elementos de la UI en el momento del cambio. No encontré ningún método de delegado para esto. ¿Cómo puedo conseguir esto?
Código:
[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];
Lo que he intentado:
Como UICollectionView
a UIScrollView
, obtuve cuando el desplazamiento del usuario finaliza con el método UIScrollViewDelegate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
Pero dentro de la función anterior, ¿cómo puedo obtener el índice de celda visible actual de UICollectionView
???
Para 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)
}
UICollectionView índice de celda visible actual: Swift 3
var visibleCurrentCellIndexPath: IndexPath? {
for cell in self.collectionView.visibleCells {
let indexPath = self.collectionView.indexPath(for: cell)
return indexPath
}
return nil
}
El método [collectionView visibleCells] le da a usted toda la matriz visibleCells que desee. Úselo cuando quiera obtener
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
for (UICollectionViewCell *cell in [self.mainImageCollection visibleCells]) {
NSIndexPath *indexPath = [self.mainImageCollection indexPathForCell:cell];
NSLog(@"%@",indexPath);
}
}
Esta es una vieja pregunta, pero en mi caso ...
- (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;
}
Para completar, este es el método que terminó trabajando para mí. Era una combinación de los métodos 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);
}
Probablemente sea mejor usar los métodos 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)
}
Puede usar scrollViewDidEndDecelerating
: para esto
//@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);
}
}
Respuestas de trabajo combinadas en 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 y 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)
}
Solo quiero agregar para otros: por alguna razón, no obtuve la celda que era visible para el usuario cuando estaba desplazándome a la celda anterior en collectionView con pagingEnabled.
Así que inserto el código dentro de dispatch_async para darle un poco de "aire" y esto funciona para mí.
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
dispatch_async(dispatch_get_main_queue(), ^{
UICollectionViewCell * visibleCell= [[self.collectionView visibleCells] objectAtIndex:0];
[visibleCell doSomthing];
});
}
Swift 3.0
La solución más simple que le dará indexPath para celdas visibles ..
yourCollectionView.indexPathsForVisibleItems
devolverá la matriz de indexpath.
Solo toma el primer objeto de una matriz como esta.
yourCollectionView.indexPathsForVisibleItems.first
Supongo que debería funcionar bien con Objective-C también.
También verifique este fragmento
let isCellVisible = collectionView.visibleCells.map { collectionView.indexPath(for: $0) }.contains(inspectingIndexPath)
la conversión de la respuesta de @ Anthony a Swift 3.0 funcionó perfectamente para mí:
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)!")
}
prueba esto, funciona (en el siguiente ejemplo, tengo 3 celdas, por ejemplo)
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let visibleRect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size)
let visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect))
let visibleIndexPath = self.collectionView.indexPathForItemAtPoint(visiblePoint)
if let v = visibleIndexPath {
switch v.item {
case 0: setImageDescription()
break
case 1: setImageConditions()
break
case 2: setImageResults()
break
default: break
}
}
indexPathsForVisibleItems
podría funcionar para la mayoría de las situaciones, pero a veces devuelve una matriz con más de una ruta de índice y puede ser complicado encontrar la que desee. En esas situaciones, puedes hacer algo como esto:
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];
Esto funciona especialmente bien cuando cada elemento en su vista de colección ocupa toda la pantalla.
Versión 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)