Evitar el "envoltorio" de elementos en UICollectionView

Necesito un UICollectionView para mostrar una cuadrícula que es potencialmente más grande que el marco visible en ancho y alto, manteniendo la integridad de fila y columna. El UICollectionViewFlowLayout pnetworkingeterminado permite que las secciones se desplacen fuera de la pantalla, pero envuelve elementos dentro de una sección para mantenerlos en pantalla, lo que daña mi cuadrícula.

Reconociendo que UICollectionView es una subclass de UIScrollView , intenté simplemente establecer manualmente la propiedad de tamaño de contenido de la vista de colección en viewDidLoad:

 self.collectionView.contentSize = CGSizeMake((columns * (cellWidth + itemSpacingX), (rows * (cellHeight + itemSpacingY)); 

Pero esto no tuvo efecto. Preguntas:

  • ¿Hay una manera fácil de lograr esto sin crear un layout personalizado?
  • ¿Utilizar un layout personalizado y anular el método collectionViewContentSize logrará que la vista de colección deje de envolver elementos y se desplace en ambas direcciones?
  • Si tengo que build un layout personalizado, que tendré que invertir algo de time para aprender, ¿subclass UICollectionViewLayout o subclassaré UICollectionViewFlowLayout ahorrar time?

ACTUALIZACIÓN: Intenté incrustar UICollectionView como una subview de un UIScrollView. La vista de colección en sí misma se comporta correctamente: las filas no se envuelven en el borde de la vista de desplazamiento y me dicen que está llenando el tamaño de contenido de UIScrollView que establezco. Pero la vista de desplazamiento no se desplaza en la dirección horizontal, es decir, solo se desplaza verticalmente, lo que la vista de colección hace por sí misma de todos modos. Tan atrapado de nuevo. ¿Podría haber un problema con la cadena de respuesta?

Imaginé dos forms de hacer esto. Ambos requieren un layout personalizado. El problema es que el layout de flujo pnetworkingeterminado, y ahora lo sé de la Guía de progtwigción de la vista de colección, es en parte la definición de un layout de flujo, genera los attributes de layout de la celda en function de los límites de la supervisión y envuelve los elementos en un sección para mantenerlos dentro de los límites de forma que el desplazamiento se produzca en un solo eje. Saltará los detalles del código, ya que no es difícil, y mi problema fue principalmente la confusión sobre qué enfoque tomar.

De manera fácil: utilice una UIScrollView y la subclass 'UICollectionViewFlowLayout'. UICollectionView el UICollectionView en un UIScrollView . Establezca la propiedad contentSize de la vista de desplazamiento en viewDiDLoad para que coincida con el tamaño completo que ocupará su vista de colección (esto permitirá que el layout de flujo pnetworkingeterminado coloque elementos en una sola línea dentro de una sección sin envolver). Subclass UICollectionViewFlowLayout y establezca ese object como su layout personalizado para la vista de colección. En el layout de flujo personalizado, reemplace collectionViewContentSize para devolver el tamaño completo de la matriz de vista de colección. Con este enfoque, utilizará un layout de flujo, pero podrá desplazarse en ambas direcciones para ver las secciones sin envolver. La desventaja es que todavía tiene un layout de flujo que es bastante limitado. Además, parece torpe poner una UICollectionView dentro de una instancia de su propia superclass solo para get la funcionalidad que debería tener la vista de colección por sí misma.

Más difícil, pero más versátil y elegante: subclass UICollectionViewLayout. Utilicé este tutorial para aprender a implementar un layout personalizado completo. No necesitas un UIScrollView aquí. Si renuncias al layout de flujo, subclass UICollectionViewLayout , y lo estableces como el layout personalizado, puedes crear la matriz y get el comportamiento correcto de la vista de colección. Es más trabajo porque debes generar todos los attributes de layout, pero estarás posicionado para que la vista de colección haga lo que quieras.

En mi opinión, Apple debería agregar una propiedad al layout de flujo pnetworkingeterminado que suprime el envoltorio. Obtener un dispositivo para mostrar una matriz 2D con filas y columnas intactas no es una funcionalidad exótica y parece que debería ser más fácil de hacer.

Aquí está la matriz completa customLayout:

 import UIKit class MatrixLayout: UICollectionViewLayout { var itemSize: CGSize! var interItemSpacingY: CGFloat! var interItemSpacingX: CGFloat! var layoutInfo: Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>! requinetworking init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) itemSize = CGSizeMake(50.0, 50.0) interItemSpacingY = 1.0 interItemSpacingX = 1.0 } override func prepareLayout() { var cellLayoutInfo = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>() let sectionCount = self.collectionView?.numberOfSections() var indexPath = NSIndexPath(forItem: 0, inSection: 0) for (var section = 0; section < sectionCount; section += 1) { let itemCount = self.collectionView?.numberOfItemsInSection(section) for (var item = 0; item < itemCount; item += 1) { indexPath = NSIndexPath(forItem:item, inSection: section) let itemAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) itemAttributes.frame = frameForCellAtIndexPath(indexPath) cellLayoutInfo[indexPath] = itemAttributes } self.layoutInfo = cellLayoutInfo } } func frameForCellAtIndexPath(indexPath: NSIndexPath) -> CGRect { let row = indexPath.section let column = indexPath.item let originX = (self.itemSize.width + self.interItemSpacingX) * CGFloat(column) let originY = (self.itemSize.height + self.interItemSpacingY) * CGFloat(row) return CGRectMake(originX, originY, self.itemSize.width, self.itemSize.height) } override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var allAttributes = Array<UICollectionViewLayoutAttributes>() for (index, attributes) in self.layoutInfo { if (CGRectIntersectsRect(rect, attributes.frame)) { allAttributes.append(attributes) } } return allAttributes } override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { return self.layoutInfo[indexPath] } override func collectionViewContentSize() -> CGSize { let width:CGFloat = (self.itemSize.width + self.interItemSpacingX) * CGFloat((self.collectionView?.numberOfItemsInSection(0))!) let height:CGFloat = (self.itemSize.height + self.interItemSpacingY) * CGFloat((self.collectionView?.numberOfSections())!) return CGSizeMake(width, height) } } 

Las secciones son filas, los elementos son columnas.