Cree un método para determinar dinámicamente qué UICollectionViewCell está en el centro de la pantalla

Actualmente estoy trabajando en una aplicación Objective-C iOS que presenta Scene con una vista de colección de pantalla completa con celdas casi del tamaño de toda la pantalla que se desplazan verticalmente por la escena.

Quiero poder cambiar la celda de manera programática en esta Vista de colección que está en el centro de la pantalla visible y la forma en que actualmente estoy logrando esta funcionalidad es esperar que el desplazamiento se detenga en la Vista de Colección y luego editar lo que sea la celda se coloca en el centro de la pantalla como se ve en el siguiente método:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{ NSIndexPath *centerCellIndexPath = [self.collectionViewFollwersFeed indexPathForItemAtPoint: [self.view convertPoint:[self.view center] toView:self.collectionViewFollwersFeed]]; UICollectionViewCell *cell; NSString *CellIdentifier; CellIdentifier = @"FollowersFeed"; cell = [_collectionViewFollwersFeed cellForItemAtIndexPath:centerCellIndexPath]; //edit cell here } 

Si bien este método de llevar a cabo esta funcionalidad funciona en cierta medida, los cambios en la célula solo comienzan cuando el usuario deja de desplazarse.

Quiero poder comenzar a hacer cambios en la celda central en el momento en que una nueva celda cubre la position central, sin tener que detener el desplazamiento. ¿Cómo podría editar este método para que si y solo si una nueva celda cubre la position central de la pantalla, se debería llamar a este método?

No pude estar más de acuerdo con mi compañero educado.

Dicho esto, es posible que desee animar algo de acuerdo con la position de desplazamiento y no solo "cambiar" la celda cuando golpea el centro …

Para hacer eso, podrías hacer que la célula haga un seguimiento de su propia position:

Pase la vista de desplazamiento a la celda en instancia:

 // MyCollectionView's DataSource - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"yourIdentifier" forIndexPath:indexPath]; cell.observedScrollView = theScrollViewYouWantToTrack; [cell startObservingPosition]; return cell; } 

Asegúrese de que la celda contenga weakly observedScrollView , para evitar un ciclo de retención

Luego, en el file .m de su celda, registre un observador KVO:

 // MyCollectionViewCell.m - (void)startObservingPosition { if (self.observedScrollView) { [self.observedScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:NULL]; } } 

Asegúrate de eliminar el observador KVO antes de que la celda se desasigne … ¡o se bloquee! también puede considerar usar un buen observador KVO mejorado que construí que se libera automáticamente

Cada vez que el Observador KVO dispara (cuando se desplaza ScrollView), puede descifrar la position y reactjsr en consecuencia.

Este ejemplo muestra cómo detectar cuándo la celda está en el centro, pero también ilustra cómo puede hacer mucho más:

 // MyCollectionViewCell.m - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context { if ([keyPath isEqualToString:@"contentOffset"]) { if (self.observedScrollView) { CGPoint offset = self.observedScrollView.contentOffset; CGRect contentViewRect = [self.contentView convertRect:self.contentView.bounds toView:self.observedScrollView]; CGFloat contentViewCenterY = contentViewRect.origin.y + contentView.size.height * 0.5 - offset.y; if (contentViewCenterY == self.observedScrollView.bounds.height * 0.5) { // the contentView is in the center of the viewable feed. do your animations... } } } } 

Edición de una celda == Yuck. Cambiar el model == agradable.

Por lo tanto, agregue un NSInteger a la indexOverCenter datos como indexOverCenter . Inicialízalo a algo no válido, como -1. Luego, en el delegado, detecte la condición:

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ NSIndexPath *centerCellIndexPath = [self.collectionViewFollwersFeed indexPathForItemAtPoint: [self.view convertPoint:[self.view center] toView:self.collectionViewFollwersFeed]]; self.indexOverCenter = centerCellIndexPath.row; // don't edit the cell here: yuck // reload it: nice [self.collectionViewFollwersFeed reloadItemsAtIndexPaths:@[ centerCellIndexPath ]]; } 

Haga su trabajo de "edición" en cellForItemAtIndex, comparando la fila indePath pasada a indexOverCenter. Si son iguales, haz tu formateo especial allí.

En mi CollectionView lo he derivado así:

 private func findCenterIndex() -> Int { let center = self.view.convert(numberCollectionView.center, to: self.numberCollectionView) let row = numberCollectionView!.indexPathForItem(at: center)?.row guard let index = row else { return 0 } self.rating = index return index } 

Entonces, puedes convertirlo fácilmente a tu código objective-c