Как сделать простой просмотр коллекции с помощью Swift


182

Я пытаюсь научиться использовать UICollectionView. Документация немного трудно понять , и уроки , которые я нашел , были либо в Objective C или долго сложных проектов.

Когда я изучал, как использовать UITableView, мы ❤ Swift's Как сделать простое табличное представление с iOS 8 и Swift имели очень простую настройку и объяснение, чтобы заставить меня работать. Есть ли что-нибудь подобное для UICollectionView?

Ответ ниже - моя попытка научиться делать это.

Ответы:


501

Этот проект был протестирован с Xcode 10 и Swift 4.2.

Создать новый проект

Это может быть только одно приложение.

Добавьте код

Создайте новый файл Cocoa Touch Class («Файл»> «Создать»> «Файл»> «iOS»> «Какао Touch Class»). Назовите это MyCollectionViewCell. Этот класс будет содержать выходы для представлений, которые вы добавляете в свою ячейку в раскадровке.

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

Мы подключим эту розетку позже.

Откройте ViewController.swift и убедитесь, что у вас есть следующее содержимое:

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)!")
    }
}

Ноты

  • UICollectionViewDataSourceи UICollectionViewDelegateпротоколы, которым следует представление коллекции. Вы также можете добавить UICollectionViewFlowLayoutпротокол для изменения размера представлений программно, но это не обязательно.
  • Мы просто помещаем простые строки в нашу сетку, но вы наверняка сможете сделать изображения позже.

Настройте раскадровку

Перетащите представление коллекции в контроллер представления на вашей раскадровке. Вы можете добавить ограничения, чтобы заполнить родительский вид, если хотите.

введите описание изображения здесь

Убедитесь, что ваши значения по умолчанию в Инспекторе атрибутов также

  • Предметы: 1
  • Макет: поток

Небольшое поле в левом верхнем углу представления коллекции - это ячейка представления коллекции. Мы будем использовать его как наш прототип ячейки. Перетащите ярлык в ячейку и отцентрируйте его. Вы можете изменить размеры границ ячейки и добавить ограничения, чтобы центрировать метку, если хотите.

введите описание изображения здесь

Напишите «ячейка» (без кавычек) в поле «Идентификатор» инспектора атрибутов для ячейки представления коллекции. Обратите внимание, что это то же значение, что и let reuseIdentifier = "cell"в ViewController.swift.

введите описание изображения здесь

А в Identity Inspector для ячейки задайте имя класса MyCollectionViewCell, наш пользовательский класс, который мы создали.

введите описание изображения здесь

Подключить розетки

  • Крючок надписи в ячейке коллекции , чтобы myLabelв MyCollectionViewCellклассе. (Вы можете перетащить Control .)
  • Хук Collection View delegateи dataSourceк View Controller. (Щелкните правой кнопкой мыши «Представление коллекции» в структуре документа. Затем щелкните и перетащите стрелку «плюс» вверх в контроллер представления.)

введите описание изображения здесь

Законченный

Вот как это выглядит после добавления ограничений для центрирования метки в ячейке и закрепления представления коллекции на стенах родительского элемента.

введите описание изображения здесь

Делать улучшения

Приведенный выше пример работает, но довольно уродливо. Вот несколько вещей, с которыми вы можете играть:

Фоновый цвет

В Интерфейсном Разработчике перейдите к Вашему Представлению Коллекции> Инспектор Атрибутов> Представление> Фон .

Расстояние между ячейками

Изменение минимального расстояния между ячейками на меньшее значение делает его лучше. В Интерфейсном Разработчике перейдите к Вашему Представлению Коллекции> Инспектор размера> Минимальный интервал и уменьшите значения. «Для ячеек» - это горизонтальное расстояние, а «Для линий» - это вертикальное расстояние.

Форма ячейки

Если вам нужны закругленные углы, границы и т.п., вы можете поиграть с клеткой layer. Вот пример кода. Вы бы поставили это сразу после cell.backgroundColor = UIColor.cyanкода выше.

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

Посмотрите этот ответ для других вещей, которые вы можете сделать со слоем (например, тень).

Изменение цвета при нажатии

Это облегчает работу пользователя, когда клетки визуально реагируют на нажатия. Один из способов добиться этого - изменить цвет фона во время прикосновения к ячейке. Для этого добавьте следующие два метода в ваш ViewControllerкласс:

// 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
}

Вот обновленный вид:

введите описание изображения здесь

Дальнейшее обучение

UITableView версия этого Q & A


1
я получаю cell.myLabel как ноль, и он падает. есть идеи почему? Я использую пользовательский макет
Джеральд

4
Если вы не подключить к розетке с помощью управления проволочки от метки в раскадровке к @IBOutletдля myLabelв коде, вы получите аварии , как это.
Сурагч

3
Если вы используете конструктор интерфейса и ссылаетесь на ячейку с помощью розетки, не регистрируйте пользовательский класс ячейки в вашем контроллере. увидеть это
Джеральд

1
если выход UICollectionViewCell равен нулю, вы должны удалить его self.collectionView.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell"). Если у вас все еще есть проблема, проверьте, есть ли reuseIdentifierтакая же dequeueReusableCellWithReuseIdentifierи в раскадровке
Ashok R

40
Я хотел бы, чтобы документация Apple была так же легко читалась, как и это объяснение
elmarko

3

Делегаты и источники данных 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
}

3

Для 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
}

1

Реализация UICollectionView довольно интересна. Вы можете использовать простой исходный код и посмотреть видеоурок по следующим ссылкам:

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)
    }

}

0

UICollectionView - это то же самое, что и UITableView, но он дает нам дополнительные функциональные возможности простого создания вида сетки, что немного проблематично в UITableView. Это будет очень длинный пост, я упомяну ссылку, откуда вы получите все в простых шагах.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.