Bien, la respuesta es no, no hay manera de hacer esto sin subclasificar UICollectionViewFlowLayout.
Sin embargo, subclasificarlo es increíblemente fácil para cualquiera que lea esto en el futuro.
Primero configuré la llamada de subclase MyCollectionViewFlowLayout
y luego en el generador de interfaz cambié el diseño de la vista de colección a Personalizado y seleccioné mi subclase de diseño de flujo.
Debido a que lo está haciendo de esta manera, no puede especificar tamaños de elementos, etc.en IB, así que en MyCollectionViewFlowLayout.m tengo esto ...
- (void)awakeFromNib
{
self.itemSize = CGSizeMake(75.0, 75.0);
self.minimumInteritemSpacing = 10.0;
self.minimumLineSpacing = 10.0;
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(10.0, 10.0, 10.0, 10.0);
}
Esto configura todos los tamaños para mí y la dirección de desplazamiento.
Luego ...
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat horizontalOffset = proposedContentOffset.x + 5;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray *array = [super layoutAttributesForElementsInRect:targetRect];
for (UICollectionViewLayoutAttributes *layoutAttributes in array) {
CGFloat itemOffset = layoutAttributes.frame.origin.x;
if (ABS(itemOffset - horizontalOffset) < ABS(offsetAdjustment)) {
offsetAdjustment = itemOffset - horizontalOffset;
}
}
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}
Esto asegura que el desplazamiento finalice con un margen de 5,0 en el borde izquierdo.
Eso es todo lo que necesitaba hacer. No necesitaba establecer el diseño de flujo en código en absoluto.
targetContentOffsetForProposedContentOffset:withVelocity
no me llaman cuando me desplazo. ¿Que esta pasando?La solución de Dan es defectuosa. No maneja bien el movimiento del usuario. Los casos en los que el usuario hace un movimiento rápido y el desplazamiento no se mueve tanto, tienen problemas de animación.
Mi implementación alternativa propuesta tiene la misma paginación que la propuesta anteriormente, pero maneja al usuario desplazarse entre páginas.
fuente
Versión rápida de la respuesta aceptada.
Válido para Swift 5 .
fuente
Aquí está mi implementación en Swift 5 para la paginación vertical basada en celdas:
Algunas notas:
itemSize
realmente coincide con el tamaño del artículo, ya que a menudo es un problema, especialmente cuando se usacollectionView(_:layout:sizeForItemAt:)
, use una variable personalizada con itemSize en su lugar.self.collectionView.decelerationRate = UIScrollView.DecelerationRate.fast
.Aquí hay una versión horizontal (no la he probado a fondo, así que perdone cualquier error):
Este código se basa en el código que utilizo en mi proyecto personal, puede consultarlo aquí descargándolo y ejecutando el destino de ejemplo.
fuente
Si bien esta respuesta ha sido de gran ayuda para mí, hay un parpadeo notable cuando se desliza rápido en una pequeña distancia. Es mucho más fácil reproducirlo en el dispositivo.
Descubrí que esto siempre sucede cuando
collectionView.contentOffset.x - proposedContentOffset.x
yvelocity.x
tengo diferentes canciones.Mi solución fue asegurarme de que
proposedContentOffset
sea más quecontentOffset.x
si la velocidad es positiva y menos si es negativa. Está en C # pero debería ser bastante simple de traducir a Objective C:Este código está usando
MinContentOffset
,MaxContentOffset
ySnapStep
debería ser trivial para definir. En mi caso resultaron serfuente
Después de largas pruebas, encontré una solución para ajustar al centro con un ancho de celda personalizado (cada celda tiene un ancho diferencial) que corrige el parpadeo. Siéntete libre de mejorar el guión.
fuente
consulte esta respuesta de Dan Abramov aquí está la versión Swift
o resumen aquí https://gist.github.com/katopz/8b04c783387f0c345cd9
fuente
Para cualquiera que busque una solución que ...
collectionView.contentInset
en consideración (y safeArea en iPhone X)entonces por favor mira abajo ...
fuente
Aquí está mi solución Swift en una vista de colección de desplazamiento horizontal. Es simple, dulce y evita cualquier parpadeo.
fuente
itemSize
??pageWidth()
debe usarminimumLineSpacing
ya que se desplaza horizontalmente. Y en mi caso, tengo unacontentInset
vista de colección para que la primera y la última celda se puedan centrar, así que usolet xOffset = pageWidth() * index - collectionView.contentInset.left
.un pequeño problema que encontré al usar targetContentOffsetForProposedContentOffset es un problema con la última celda que no se ajusta de acuerdo con el nuevo punto que devolví.
Descubrí que el CGPoint que devolví tenía un valor Y mayor que el permitido, así que usé el siguiente código al final de mi implementación targetContentOffsetForProposedContentOffset:
para que quede más claro, esta es mi implementación de diseño completo que solo imita el comportamiento de paginación vertical:
con suerte esto le ahorrará a alguien algo de tiempo y dolor de cabeza
fuente
Prefiero permitir que el usuario hojee varias páginas. Así que aquí está mi versión de
targetContentOffsetForProposedContentOffset
(que se basa en la respuesta de DarthMike) para el diseño vertical .fuente
La respuesta de Fogmeisters funcionó para mí a menos que me desplazara hasta el final de la fila. Mis celdas no encajan perfectamente en la pantalla, por lo que se desplazaría hasta el final y saltaría hacia atrás con un tirón para que la última celda siempre se superpusiera al borde derecho de la pantalla.
Para evitar esto, agregue la siguiente línea de código al comienzo del método targetcontentoffset
fuente
@ André Abreu 's Code
Versión Swift3
fuente
Rápido 4
La solución más sencilla para la vista de colección con celdas de un tamaño (desplazamiento horizontal):
fuente
Una solución más corta (asumiendo que está almacenando en caché sus atributos de diseño):
Para poner esto en contexto:
fuente
Para asegurarme de que funciona en la versión Swift (swift 5 ahora), usé la respuesta de @ André Abreu, agrego más información:
Cuando se subclasifica UICollectionViewFlowLayout, el "override func awakeFromNib () {}" no funciona (no sé por qué). En su lugar, usé "anular init () {super.init ()}"
Este es mi código puesto en la clase SubclassFlowLayout: UICollectionViewFlowLayout {}:
Después de subclasificar, asegúrese de poner esto en ViewDidLoad ():
fuente
Para aquellos que buscan una solución en Swift:
fuente
Aquí hay una demostración para paginar por celda (cuando se desplaza rápido, sin omitir una o más celdas): https://github.com/ApesTalk/ATPagingByCell
fuente