Como criar uma visualização de coleção simples com o Swift

181

Estou tentando aprender a usar UICollectionView. A documentação é um pouco difícil de entender e os tutoriais que encontrei estavam no Objective C ou em projetos muito complicados.

Quando eu estava aprendendo a usar UITableView, o We ❤ Swift's Como fazer uma simples tableview com o iOS 8 e o Swift tinha uma configuração e uma explicação muito básicas para me ajudar . Existe algo assim para UICollectionView?

A resposta abaixo é minha tentativa de aprender a fazer isso.

Suragch
fonte

Respostas:

500

Este projeto foi testado com o Xcode 10 e o Swift 4.2.

Crie um novo projeto

Pode ser apenas um aplicativo de exibição única.

Adicione o código

Crie um novo arquivo Cocoa Touch Class (Arquivo> Novo> Arquivo ...> iOS> Cocoa Touch Class). Dê um nome MyCollectionViewCell. Esta classe manterá as saídas das visualizações adicionadas ao seu celular no storyboard.

import UIKit
class MyCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var myLabel: UILabel!
}

Mais tarde conectaremos esta tomada.

Abra o ViewController.swift e verifique se você tem o seguinte conteúdo:

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, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        // get a reference to our storyboard cell
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as 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.cyan // make cell more visible in our example project
        
        return cell
    }
    
    // MARK: - UICollectionViewDelegate protocol
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // handle tap events
        print("You selected cell #\(indexPath.item)!")
    }
}

Notas

  • UICollectionViewDataSourcee UICollectionViewDelegatesão os protocolos que a exibição da coleção segue. Você também pode adicionar o UICollectionViewFlowLayoutprotocolo para alterar o tamanho das visualizações programaticamente, mas não é necessário.
  • Estamos apenas colocando cordas simples em nossa grade, mas você certamente poderá fazer imagens posteriormente.

Configurar o storyboard

Arraste uma View de coleção para o View Controller no seu storyboard. Você pode adicionar restrições para preencher a visualização principal, se desejar.

insira a descrição da imagem aqui

Verifique se seus padrões no Inspetor de atributos também estão

  • Itens: 1
  • Layout: Fluxo

A pequena caixa no canto superior esquerdo da exibição de coleção é uma célula de exibição de coleção. Vamos usá-lo como nossa célula protótipo. Arraste um rótulo para a célula e centralize-o. Você pode redimensionar as bordas da célula e adicionar restrições para centralizar o Label, se desejar.

insira a descrição da imagem aqui

Escreva "célula" (sem aspas) na caixa Identificador do Inspetor de atributos para a célula de exibição de coleção. Observe que esse é o mesmo valor que let reuseIdentifier = "cell"em ViewController.swift.

insira a descrição da imagem aqui

E no Identity Inspector da célula, defina o nome da classe como MyCollectionViewCell, nossa classe personalizada que criamos.

insira a descrição da imagem aqui

Ligar as tomadas

  • Conecte o Label na célula de coleção myLabelna MyCollectionViewCellclasse. (Você pode pressionar a tecla Control e arrastar .)
  • Conecte o modo de exibição de coleção delegatee dataSourceo controlador de exibição. (Clique com o botão direito do mouse em Modo de exibição de coleção no Resumo do documento. Em seguida, clique e arraste a seta mais até o Controlador de exibição.)

insira a descrição da imagem aqui

Acabado

Aqui está o que parece depois de adicionar restrições para centralizar o Rótulo na célula e fixar a Exibição de Coleção nas paredes do pai.

insira a descrição da imagem aqui

Fazendo melhorias

O exemplo acima funciona, mas é bastante feio. Aqui estão algumas coisas com as quais você pode jogar:

Cor de fundo

No Construtor de interface, vá para o Modo de exibição de coleção> Inspetor de atributos> Exibir> Plano de fundo .

Espaçamento celular

Alterar o espaçamento mínimo entre células para um valor menor faz com que pareça melhor. No Construtor de interface, acesse Exibição da coleção> Inspetor de tamanho> Espaçamento mínimo e diminua os valores. "Para células" é a distância horizontal e "Para linhas" é a distância vertical.

Forma da célula

Se você quiser cantos arredondados, uma borda e coisas do gênero, pode brincar com a célula layer. Aqui está um código de exemplo. Você o colocaria diretamente depois cell.backgroundColor = UIColor.cyanno código acima.

cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 1
cell.layer.cornerRadius = 8

Veja esta resposta para outras coisas que você pode fazer com a camada (sombra, por exemplo).

Alterar a cor ao tocar

Isso contribui para uma melhor experiência do usuário quando as células respondem visualmente aos toques. Uma maneira de conseguir isso é alterar a cor do plano de fundo enquanto a célula está sendo tocada. Para fazer isso, adicione os dois métodos a seguir à sua ViewControllerclasse:

// change background color when user touches cell
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.red
}

// change background color back when user releases touch
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.cyan
}

Aqui está a aparência atualizada:

insira a descrição da imagem aqui

Um estudo mais aprofundado

Versão UITableView deste Q&A

Suragch
fonte
1
Estou recebendo cell.myLabel como nulo e está falhando. Alguma idéia do porquê? Im usando um layout personalizado
Gerald
4
Se você não conectasse a tomada arrastando a etiqueta do marcador no storyboard para o código @IBOutletfor myLabelno controle , ocorreria uma falha como esta.
Suragch
3
se você estiver usando o construtor de interface e referenciar a célula usando uma tomada, não registre a classe de célula personalizada em seu controlador. veja isso
Gerald
1
se a saída UICollectionViewCell for nula, você deverá remover self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Se você ainda tiver o cheque problema wether reuseIdentifieré mesmo no dequeueReusableCellWithReuseIdentifiere no storyboard
Ashok R
40
Desejo documentação da Apple era tão fácil de ler como esta explicação
elmarko
3

Delegados e fontes de dados do UICollectionView

//MARK: UICollectionViewDataSource

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1     //return number of sections in collection view
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10    //return number of rows in section
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("collectionCell", forIndexPath: indexPath)
    configureCell(cell, forItemAtIndexPath: indexPath)
    return cell      //return your cell
}

func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
    cell.backgroundColor = UIColor.blackColor()


    //Customise your cell

}

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    let view =  collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", forIndexPath: indexPath) as UICollectionReusableView
    return view
}

//MARK: UICollectionViewDelegate
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
      // When user selects the cell
}

override func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
     // When user deselects the cell
}
Saranjith
fonte
3

Para swift 4.2-

//MARK: UICollectionViewDataSource

func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1     //return number of sections in collection view
}

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10    //return number of rows in section
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath)
    configureCell(cell: cell, forItemAtIndexPath: indexPath)
    return cell      //return your cell
}

func configureCell(cell: UICollectionViewCell, forItemAtIndexPath: NSIndexPath) {
    cell.backgroundColor = UIColor.black


    //Customise your cell

}

func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    let view =  collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as UICollectionReusableView
    return view
}

//MARK: UICollectionViewDelegate
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    // When user selects the cell
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    // When user deselects the cell
}
Abhishek Mishra
fonte
1

A implementação do UICollectionView é bastante interessante. Você pode usar o código-fonte simples e assistir a um tutorial em vídeo usando estes links:

https://github.com/Ady901/Demo02CollectionView.git

https://www.youtube.com/watch?v=5SrgvZF67Yw

extension ViewController : UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return nameArr.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DummyCollectionCell", for: indexPath) as! DummyCollectionCell
        cell.titleLabel.text = nameArr[indexPath.row]
        cell.userImageView.backgroundColor = .blue
        return cell
    }

}

extension ViewController : UICollectionViewDelegate {

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let alert = UIAlertController(title: "Hi", message: "\(nameArr[indexPath.row])", preferredStyle: .alert)
        let action = UIAlertAction(title: "OK", style: .default, handler: nil)
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
    }

}
Aditya Sharma
fonte
0

UICollectionView é o mesmo que UITableView, mas fornece a funcionalidade adicional de simplesmente criar uma exibição em grade, o que é um pouco problemático no UITableView. Será um post muito longo. Mencionei um link de onde você obterá tudo em etapas simples.

Dilraj Singh
fonte