iOS
UICollectionView
Buscar..
Crear una vista de colección programáticamente
Rápido
func createCollectionView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height), collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
view.addSubview(collectionView)
}
C objetivo
- (void)createCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[self.view addSubview:collectionView];
}
Swift - UICollectionViewDelegateFlowLayout
// MARK: - UICollectionViewDelegateFlowLayout
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 50, height: 50)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 5.0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 5.0
}
}
Crear un UICollectionView
Inicialice un UICollectionView
con un marco CGRect
:
Rápido:
let collection = UICollectionView(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
C objetivo:
UICollectionView *collection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, 200, 21)];
También puede crear un UICollectionView
en Interface Builder
UICollectionView - Fuente de datos
Cada vista de colección debe tener un objeto Datasource
. El objeto Datasource
es el contenido que su aplicación mostrará dentro de UICollectionView
. Como mínimo, todos los objetos Datasource
deben implementar los métodos collectionView:numberOfItemsInSection:
y collectionView:cellForItemAtIndexPath:
Métodos requeridos
Rápido
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// Return how many items in section
let sectionArray = _data[section]
return sectionArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(MyCellID)
// If you use a custom cell class then cast the cell returned, like:
// as! MyCollectionViewCellClass
// or you will have errors when you try to use features of that class.
//Customize your cell here, default UICollectionViewCells do not contain any inherent
//text or image views (like UITableView), but some could be added,
//or a custom UICollectionViewCell sub-class could be used
return cell
}
C objetivo
- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section {
// Return how many items in section
NSArray *sectionArray = [_data objectAtIndex:section];
return [sectionArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// Return a cell
UICollectionViewCell *newCell = [self.collectionView
dequeueReusableCellWithReuseIdentifier:MyCellID
forIndexPath:indexPath];
//Customize your cell here, default UICollectionViewCells do not contain any inherent
//text or image views (like UITableView), but some could be added,
//or a custom UICollectionViewCell sub-class could be used
return newCell;
}
Ejemplo Swift básico de una vista de colección
Crear un nuevo proyecto
Puede ser solo una aplicación de vista única.
Agrega el codigo
Cree un nuevo archivo Cocoa Touch Class (Archivo> Nuevo> Archivo ...> iOS> Clase Cocoa Touch). MyCollectionViewCell
. Esta clase contendrá los puntos de venta de las vistas que agregue a su celda en el guión gráfico.
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var myLabel: UILabel!
}
Vamos a conectar esta salida más tarde.
Abra ViewController.swift y asegúrese de tener el siguiente contenido:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
let reuseIdentifier = "cell" // also enter this string as the cell identifier in the storyboard
var items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"]
// MARK: - UICollectionViewDataSource protocol
// tell the collection view how many cells to make
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
// make a cell for each cell index path
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.myLabel.text = self.items[indexPath.item]
cell.backgroundColor = UIColor.yellowColor() // make cell more visible in our example project
return cell
}
// MARK: - UICollectionViewDelegate protocol
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
}
Notas
-
UICollectionViewDataSource
yUICollectionViewDelegate
son los protocolos que sigue la vista de colección. También puede agregar el protocoloUICollectionViewDelegateFlowLayout
para cambiar el tamaño de las vistas mediante programación, pero no es necesario. - Solo estamos colocando cadenas simples en nuestra cuadrícula, pero ciertamente podrías hacer imágenes más tarde.
Configurar el guión gráfico
Arrastre una vista de colección al controlador de vista en su guión gráfico. Puede agregar restricciones para que llene la vista principal si lo desea.
Asegúrese de que sus valores predeterminados en el inspector de atributos también estén
- Artículos: 1
- Diseño: Flujo
El pequeño cuadro en la parte superior izquierda de la vista de colección es una celda de vista de colección. Lo usaremos como nuestro prototipo de célula. Arrastre una etiqueta a la celda y céntrela. Puede cambiar el tamaño de los bordes de las celdas y agregar restricciones para centrar la etiqueta si lo desea.
Escriba "celda" (sin comillas) en el cuadro Identificador del inspector de atributos para la celda de vista de colección. Tenga en cuenta que este es el mismo valor que let reuseIdentifier = "cell"
en ViewController.swift.
Y en el inspector de identidad para la celda, establezca el nombre de la clase en MyCollectionViewCell
, nuestra clase personalizada que hicimos.
Conectar los puntos de venta
- Enganche la etiqueta en la celda de colección a
myLabel
en la claseMyCollectionViewCell
. (Puedes presionar Control y arrastrar .) - Enganche el
delegate
y eldataSource
dedataSource
de la vista de ladataSource
al controlador de vista. (Haga clic con el botón derecho en Vista de colección en el Esquema del documento. Luego, haga clic y arrastre la flecha más hasta el Controlador de vista).
Terminado
Así es como se ve después de agregar restricciones para centrar la Etiqueta en la celda y fijar la Vista de Colección en las paredes del padre.
Haciendo mejoras
Si desea realizar mejoras en la apariencia, consulte la publicación original de la que proviene este ejemplo .
Estudio adicional
- Un simple tutorial de UICollectionView
- UICollectionView Tutorial Part 1: Getting Started
- UICollectionView Tutorial Parte 2: Vistas reutilizables y selección de celdas
Realización de actualizaciones por lotes
Puede animar cambios complejos a su vista de colección usando el método performBatchUpdates
. Dentro del bloque de actualización, puede especificar varias modificaciones para que se animen a la vez.
collecitonView.performBatchUpdates({
// Perform updates
}, nil)
Dentro del bloque de actualización, puede realizar inserciones, eliminaciones, movimientos y recargas. Aquí es cómo determinar qué indexPath utilizar:
Tipo | NSIndexPath |
---|---|
Inserción | Índice en nueva matriz |
Supresión | Índice en matriz antigua |
Movimiento | desde: matriz antigua, a: nueva matriz |
Recargar | ya sea nueva o antigua matriz (no debería importar) |
Solo debe llamar a recargar en celdas que no se hayan movido, pero su contenido ha cambiado. Es importante tener en cuenta que un movimiento no actualizará el contenido de una celda, sino que solo moverá su ubicación.
Para verificar que la actualización por lotes se realizará correctamente, asegúrese de que el conjunto de indexPaths para deletion
, move-from
y reload
sea único, y que el conjunto de indexPaths para insertion
, move-to
y reload
sea único.
Aquí hay un ejemplo de una actualización por lotes adecuada:
let from = [1, 2, 3, 4, 5]
let to = [1, 3, 6, 4, 5]
collecitonView.performBatchUpdates({
collectionView.insertItemsAtIndexPaths([NSIndexPath(forItem: 2, inSection: 0)])
collectionView.deleteItemsAtIndexPaths([NSIndexPath(forItem: 1, inSection: 0)])
collectionView.moveItemAtIndexPath(NSIndexPath(forItem: 2, inSection: 0),
toIndexPath: NSIndexPath(forItem: 1, inSection:0))
}, nil)
UICollectionViewDelegate configuración y selección de elementos
A veces, si una acción debe estar vinculada a la selección de celda de una vista de colección, debe implementar el protocolo UICollectionViewDelegate
.
Digamos que la vista de colección está dentro de un UIViewController MyViewController
.
C objetivo
En su MyViewController.h declara que implementa el protocolo UICollectionViewDelegate
, como se muestra a continuación
@interface MyViewController : UIViewController <UICollectionViewDelegate, .../* previous existing delegate, as UICollectionDataSource *>
Rápido
En su MyViewController.swift agregue lo siguiente
class MyViewController : UICollectionViewDelegate {
}
El método que se debe implementar es
C objetivo
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
Rápido
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
}
A modo de ejemplo, podemos establecer el color de fondo de la celda seleccionada en verde.
C objetivo
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor greenColor];
}
Rápido
class MyViewController : UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
var cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
cell.backgroundColor = UIColor.greenColor()
}
}
Administrar la vista de colección múltiple con DataSource y Flowlayout
Aquí estamos administrando la colección múltiple, delegando métodos con didselect eventos.
extension ProductsVC: UICollectionViewDelegate, UICollectionViewDataSource{
// MARK: - UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard collectionView == collectionCategory else {
return arrOfProducts.count
}
return arrOfCategory.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard collectionView == collectionProduct else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductCategoryCell", for: indexPath) as! ProductCategoryCell
cell.viewBackground.layer.borderWidth = 0.5
//Do some thing as per use
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ProductCell
cell.contentView.layer.borderWidth = 0.5
cell.contentView.layer.borderColor = UIColor.black.cgColor
let json = arrOfProducts[indexPath.row]
//Do something as per use
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard collectionView == collectionCategory else {
let json = arrOfProducts[indexPath.row]
// Do something for collectionProduct here
return
}
let json = arrOfCategory[indexPath.row] as [String: AnyObject]
let id = json["cId"] as? String ?? ""
// Do something
}
}
extension ProductsVC: UICollectionViewDelegateFlowLayout{
// MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionWidth = collectionView.bounds.width
guard collectionView == collectionProduct else {
var itemWidth = collectionWidth / 4 - 1;
if(UI_USER_INTERFACE_IDIOM() == .pad) {
itemWidth = collectionWidth / 4 - 1;
}
return CGSize(width: itemWidth, height: 50)
}
var itemWidth = collectionWidth / 2 - 1;
if(UI_USER_INTERFACE_IDIOM() == .pad) {
itemWidth = collectionWidth / 4 - 1;
}
return CGSize(width: itemWidth, height: 250);
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
}