iphone - uicollectionviewcontroller - uicollectionviewcell indexpath
Desplácese programáticamente a una vista complementaria dentro de UICollectionView (4)
No puedes usar scrollToItemAtIndexPath:atScrollPosition:animated
para esto.
Con suerte, agregarán un nuevo método como scrollToSupplementaryElementOfKind:atIndexPath:
en el futuro, pero por ahora, la única forma es manipular el contentOffset directamente .
El siguiente código muestra cómo desplazar el encabezado para estar en la parte superior verticalmente con FlowLayout. Puede hacer lo mismo para el desplazamiento horizontal, o usar esta idea para otros tipos de diseño.
NSIndexPath *indexPath = ... // indexPath of your header, item must be 0
CGFloat offsetY = [collectionView layoutAttributesForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath].frame.origin.y;
CGFloat contentInsetY = self.contentInset.top;
CGFloat sectionInsetY = ((UICollectionViewFlowLayout *)collectionView.collectionViewLayout).sectionInset.top;
[collectionView setContentOffset:CGPointMake(collectionView.contentOffset.x, offsetY - contentInsetY - sectionInsetY) animated:YES];
Tenga en cuenta que si tiene contentInset
distinto de cero (como en iOS 7, cuando las vistas de desplazamiento se expanden por debajo de las barras), debe restarlo del offsetY
, como se muestra. Lo mismo para sectionInset
.
Actualizar:
El código supone que el diseño está en estado preparado, "válido" porque lo utiliza para calcular el desplazamiento. El diseño se prepara cuando la vista de colección presenta su contenido.
La llamada a [_collectionView.collectionViewLayout prepareLayout]
antes del código anterior puede ayudar cuando necesite desplazarse por la vista de la colección que aún no se ha presentado (de viewDidLoad
decir). La llamada a layoutIfNeeded
(como sugirió @Vrasidas en los comentarios) también debería funcionar porque también prepara el diseño.
Estoy usando UICollectionView
para mostrar fotos en secciones. Cada sección tiene una vista complementaria como encabezado y se proporciona a través del método: viewForSupplementaryElementOfKind
.
Tengo un limpiador en el lado que le permite al usuario saltar de una sección a otra. Por ahora me estoy desplazando al primer elemento en la sección usando scrollToItemAtIndexPath:atScrollPosition:animated:
pero lo que realmente quiero es desplazar el collectionView para que el encabezado de esa sección esté en la parte superior de la pantalla, no en la primera celda. No veo un método obvio para hacer esto. ¿Alguno de ustedes tiene un trabajo alrededor?
Supongo que podría desplazarme hasta el primer elemento de la sección y luego compensarlo con la altura suplementaria más el desplazamiento entre los elementos y el encabezado si se reduce a eso (hay un método para desplazarse a las coordenadas del punto del contentView). Sin embargo, si hay una forma más simple, me gustaría saber.
Gracias.
Solución en Swift,
let section: = 0 // Top
if let cv = self.collectionView {
cv.layoutIfNeeded()
let indexPath = NSIndexPath(forItem: 1, inSection: section)
if let attributes = cv.layoutAttributesForSupplementaryElementOfKind(UICollectionElementKindSectionHeader, atIndexPath: indexPath) {
let topOfHeader = CGPointMake(0, attributes.frame.origin.y - cv.contentInset.top)
cv.setContentOffset(topOfHeader, animated:true)
}
}
Props to Gene De Lisa: http://www.rockhoppertech.com/blog/scroll-to-uicollectionview-header/
Una cosa que las soluciones no administran es si está colocando encabezados de sección. Los métodos funcionan bien con encabezados sin pines, pero si sus encabezados están anclados, mientras se desplaza a una sección sobre la sección actual, se detendrá una vez que aparezca el encabezado de la sección (que será para la fila inferior de su sección). Eso puede ser deseable en algunos casos, pero creo que el objetivo es poner la parte superior de la sección en la parte superior de la pantalla.
En cuyo caso debe tomar los métodos anteriores y ajustarlos un poco. Por ejemplo:
UICollectionView *cv = self.collectionView;
CGFloat contentInsetY = cv.contentInset.top;
CGFloat offsetY = [cv layoutAttributesForItemAtIndexPath:ip].frame.origin.y;
CGFloat sectionHeight =
[cv layoutAttributesForSupplementaryElementOfKind:UICollectionElementKindSectionHeader atIndexPath:ip].frame.size.height;
[cv setContentOffset:CGPointMake(cv.contentOffset.x, offsetY - contentInsetY - sectionHeight) animated:YES];
Ahora, básicamente, está desplazando la primera fila de su sección a visible, menos la altura de su encabezado de sección. Esto colocará el encabezado de la sección en la parte superior donde lo desee con encabezados anclados para que la dirección del desplazamiento ya no sea importante. No probé con inserciones de sección.
// scroll to selected index
NSIndexPath* cellIndexPath = [NSIndexPath indexPathForItem:0 inSection:sectionIndex];
UICollectionViewLayoutAttributes* attr = [self.collectionView.collectionViewLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:cellIndexPath];
UIEdgeInsets insets = self.collectionView.scrollIndicatorInsets;
CGRect rect = attr.frame;
rect.size = self.collectionView.frame.size;
rect.size.height -= insets.top + insets.bottom;
CGFloat offset = (rect.origin.y + rect.size.height) - self.collectionView.contentSize.height;
if ( offset > 0.0 ) rect = CGRectOffset(rect, 0, -offset);
[self.collectionView scrollRectToVisible:rect animated:YES];