ios layout uicollectionview uicollectionviewlayout

ios - UICollectionView-desplazamiento horizontal, diseño horizontal?



layout uicollectionviewlayout (11)

Tengo un UIScrollView que establece una grilla de iconos. Si imaginas el diseño de iOS Springboard, estarías muy cerca de corregirlo. Tiene un desplazamiento horizontal, paginado (como Springboard). Sin embargo, parece que el diseño no es del todo correcto. Parece como si estuviera diseñando los elementos de arriba a abajo. Como resultado, mi última columna solo tiene 2 filas, debido a la cantidad de elementos que se mostrarán. Prefiero que mi última fila en la última página tenga 2 elementos, como los que verá en el trampolín.

¿Cómo se puede lograr esto con UICollectionView y sus clases relacionadas? ¿Debo escribir un UICollectionViewFlowLayout personalizado?


Primer acercamiento

¿Qué hay de usar UIPageViewController con una matriz de UICollectionViewControllers ? Tendría que buscar la cantidad adecuada de elementos en cada UICollectionViewController , pero no debería ser difícil. Tendrás exactamente el mismo aspecto que tiene Springboard.

Segundo enfoque

He pensado sobre esto y en mi opinión tienes que establecer:

self.collectionView.pagingEnabled = YES;

y crea tu propio diseño de vista de colección subclasificando UICollectionViewLayout . Desde el objeto de diseño personalizado, puede acceder a self.collectionView , para que sepa cuál es el tamaño del frame la vista de colección, numberOfSections y numberOfItemsInSection: Con esa información puede calcular los frames las celdas (en prepareLayout ) y collectionViewContentSize . Aquí hay algunos artículos sobre cómo crear diseños personalizados:

3º enfoque

Puede hacer esto (o una aproximación) sin crear el diseño personalizado. Agregue UIScrollView en la vista en blanco, configure la paginación habilitada en ella. En la vista de desplazamiento, agregue una vista de colección. A continuación, agregue una restricción de ancho, verifique en el código cuántos elementos tiene y establezca su constant en el valor correcto, por ejemplo (self.view.frame.size.width * numOfScreens) . Así es como se ve (los números en las celdas muestran el indexPath.row ): https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov Si no está satisfecho con la forma en que se ordenan las celdas, entonces tengo miedo tendrías que ir con 1. o 2.


¿Has intentado configurar la dirección de desplazamiento de tu UICollectionViewFlowLayout en horizontal?

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

Y si desea que la página se muestre como lo hace el trampolín, deberá habilitar la búsqueda en su vista de colección de la siguiente manera:

[yourCollectionView setPagingEnabled:YES];


De @Erik Hunter, publico el código completo para hacer UICollectionView horizontal

UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init]; [collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; self.myCollectionView.collectionViewLayout = collectionViewFlowLayout;

En Swift

let layout = UICollectionViewFlowLayout() layout.scrollDirection = .Horizontal self.myCollectionView.collectionViewLayout = layout

En Swift 3.0

let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal self.myCollectionView.collectionViewLayout = layout

Espero que esto ayude


Este código funciona bien en Swift 3.1 y Xcode 8.3.2

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let layout = UICollectionViewFlowLayout() layout.scrollDirection = .horizontal self.collectionView.collectionViewLayout = layout self.collectionView!.contentInset = UIEdgeInsets(top: -10, left: 0, bottom:0, right: 0) if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout { layout.minimumInteritemSpacing = 0 layout.minimumLineSpacing = 0 layout.itemSize = CGSize(width: self.view.frame.size.width-40, height: self.collectionView.frame.size.height-10) layout.invalidateLayout() } }


Estoy trabajando en Xcode 6.2 y para el desplazamiento horizontal he cambiado la dirección de desplazamiento en el inspector de atributos.

haga clic en collectionView-> attribute inspector-> scroll Direction-> change to horizontal

Espero que esto ayude a alguien.


Podemos hacer el mismo comportamiento de Springboard usando UICollectionView y para eso tenemos que escribir código para el diseño personalizado.

Lo logré con la implementación personalizada de la clase de diseño con "SMCollectionViewFillLayout"

Repositorio de código:

https://github.com/smindia1988/SMCollectionViewFillLayout

Salida como abajo:

1.png

2_Code_H-Scroll_V-Fill.png

3_Output_H-Scroll_V-Fill.png

4_Code_H-Scroll_H-Fill.png

5_Output_H-Scroll_H-Fill.png


Puede escribir un diseño UICollectionView personalizado para lograr esto, aquí está la imagen de demostración de mi implementación:

Aquí está el repositorio de código: KSTCollectionViewPageHorizontalLayout

@iPhoneDev (esto quizás también te ayude)


Si define UICollectionViewFlowLayout en el código, anulará las configuraciones de Interface Builder. Por lo tanto, necesita volver a definir la scrollDirection nuevamente.

let layout = UICollectionViewFlowLayout() ... layout.scrollDirection = .Horizontal self.awesomeCollectionView.collectionViewLayout = layout


Solo por diversión, otro enfoque sería simplemente dejar el juego de paginación y desplazamiento horizontal, agregar un método que cambie el orden de los elementos de la matriz para convertir de ''arriba a abajo, de izquierda a derecha'' a visualmente ''de izquierda a derecha, de arriba a abajo ''y llene las celdas intermedias con celdas ocultas vacías para hacer el espaciado correcto. En el caso de 7 elementos en una grilla de 9, esto sería así:

[1][4][7] [2][5][ ] [3][6][ ]

debe convertirse

[1][2][3] [4][5][6] [7][ ][ ]

entonces 1 = 1, 2 = 4, 3 = 7 etc. y 6 = vacío. Puede reordenarlos calculando el número total de filas y columnas, luego calcula el número de fila y columna para cada celda, cambia la fila para la columna y viceversa y luego tienes los nuevos índices. Cuando la celda no tiene un valor correspondiente a la imagen, puede devolver una celda vacía y establecer cell.hidden = YES; lo.

Funciona bastante bien en una aplicación de caja de resonancia que construí, así que si alguien quisiera trabajar en el código, lo agregaré. Solo se requiere un pequeño código para hacer que este truco funcione, ¡suena más difícil de lo que es!

Actualizar

Dudo que esta sea la mejor solución, pero a pedido aquí está el código de trabajo:

- (void)viewDidLoad { // Fill an `NSArray` with items in normal order items = [NSMutableArray arrayWithObjects: [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 1", @"label", @"Some value 1", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 2", @"label", @"Some value 2", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 3", @"label", @"Some value 3", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 4", @"label", @"Some value 4", @"value", nil], [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 5", @"label", @"Some value 5", @"value", nil], nil ]; // Calculate number of rows and columns based on width and height of the `UICollectionView` and individual cells (you might have to add margins to the equation based on your setup!) CGFloat w = myCollectionView.frame.size.width; CGFloat h = myCollectionView.frame.size.height; rows = floor(h / cellHeight); columns = floor(w / cellWidth); } // Calculate number of sections - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return ceil((float)items.count / (float)(rows * columns)); } // Every section has to have every cell filled, as we need to add empty cells as well to correct the spacing - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return rows*columns; } // And now the most important one - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier@"myIdentifier" forIndexPath:indexPath]; // Convert rows and columns int row = indexPath.row % rows; int col = floor(indexPath.row / rows); // Calculate the new index in the `NSArray` int newIndex = ((int)indexPath.section * rows * columns) + col + row * columns; // If the newIndex is within the range of the items array we show the cell, if not we hide it if(newIndex < items.count) { NSDictionary *item = [items objectAtIndex:newIndex]; cell.label.text = [item objectForKey:@"label"]; cell.hidden = NO; } else { cell.hidden = YES; } return cell; }

Si desea utilizar el método didSelectItemAtIndexPath , debe usar la misma conversión que se utiliza en cellForItemAtIndexPath para obtener el elemento correspondiente. Si tiene márgenes de celda, debe agregarlos al cálculo de filas y columnas, ya que deben ser correctos para que esto funcione.


para xcode 8 lo hice y funcionó:


UICollectionView reducir la altura de UICollectionView a la altura de su celda / elemento y seleccionar " Horizontal " desde la " Scroll Direction " como se ve en la captura de pantalla siguiente. Luego se desplazará horizontalmente según el número de elementos que haya devuelto en la implementación de su fuente de datos.