Всем привет! Сегодня тема нашего Juniors Talks — UICollectionView.
Что это такое?
UICollectionView – это объект, который хранит в себе совокупность упорядоченных элементов, отображая их с помощью кастомизированных layouts.
Пример:
Чаще всего на практике используют UICollectionView со стандартным UICollectionViewFlowLayout, который отображает элементы в виде обычной сетки и имеет только одно из двух доступных направлений прокрутки (горизонтальная/вертикальная). Но это не всё, что вы можете кастомизировать. Вы можете создать объект UICollectionViewFlowLayout() и посмотреть какие у него есть доступные свойства или почитать здесь.
Считаю, что разговор о UICollectionViewLayout можно вынести в отдельную статью, а сегодня поговорим о начальной инициализации UICollectionView & UICollectionViewCell и разных нюансах реализации.
Итак, начнём…
Для тех кому лень читать ссылка на конечный проект здесь.
Шаг 1
Создаем новый storyboard, добавляем на него viewController, к которому привяжем по всем сторонам collectionView.
Шаг 2
Создаем новый класс для VC, например GalleryViewController, наследуемся от UIViewController
import UIKit final class GalleryViewController: UIViewController { override func viewDidLoad() { } }
Шаг 3
Создадим кастомную ячейку. Для этого нам надо создать Cocoa Touch Class. Нажимаем File → New → File… в открывшимся окне выбираем Cocoa Touch Class, далее класс, от которого будем наследоваться. В нашем случае это UICollectionViewCell. Не забываем выбрать пункт «Also create XIB file»
Для примера я добавил ImageView и UILabel.
О чем не стоит забывать? Об установки reuse Identifier. Для этого нужно выбрать ячейку и в пункте «show the attributes inspector» установить идентификатор.
Вешаем outlets для выше добавленных UI компонентов.
Переходим в класс ячейки и добавляем конфигуратор:
func configure(by image: UIImage, count: Int) { imageView.image = image countLabel.text = "\(count)" }
Начальные приготовления закончены. Теперь переходим к самому интересному.
Шаг 4
Возвращаемся в наш GalleryViewController. Создаем outlet на collectionView (думаю не нуждается в комментариях)
@IBOutlet var collectionView: UICollectionView! { didSet { // 1 collectionView.delegate = self collectionView.dataSource = self // 2 collectionView.register(UINib.init(nibName: "PhotoCell", bundle: nil), forCellWithReuseIdentifier: "photoCell") collectionView.backgroundColor = .clear } }
- нужно подписаться на протоколы UICollectionViewDelegate’n’DataSource, чтобы получить доступ к методам.
- регистрируем созданный нами выше файл, чтобы использовать его при создании новых ячеек.
Теперь добавим картинки и попробуем их отобразить.
private var images = [UIImage(named: "image1")!, UIImage(named: "image2")!, UIImage(named: "image3")!, UIImage(named: "image4")!, UIImage(named: "image5")!]
Шаг 5
extension GalleryViewController: UICollectionViewDelegate, UICollectionViewDataSource { // 1 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return images.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // 2 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! PhotoCell let image = images[indexPath.row] // 3 cell.configure(by: image, count: indexPath.row + 1) return cell } }
- Метод numberOfItemsInSection обязательный. Он возвращает число элементов, которые будут отображены, в конкретной секции. В нашем случае секция одна;
- Метод dequeueReusableCell(withReuseIdentifier: String, for: IndexPath) возвращает ячейку, которую можно переиспользовать;
- Теперь когда у нас есть ячейка мы должны ее подготовить для отображения с помощью метода configure, который описали выше.
Запустим и посмотрим что получилось.
Вышло не плохо… Но давайте попробуем сделать так, чтобы на одной строке было всего три ячейки.
Для этого перейдем к заключительному шагу 6 :
Нам нужны будут методы протокола UICVDelegateFlowLayout:
- sizeForItemAt — метод задающий определенный размер ячейкам в коллекции;
- minimumLineSpacingForSectionAt — метод задающий минимальный отступ между строками, на которых располагаются ячейки;
- minimumInteritemSpacingForSectionAt — метод задающий минимальный отступ между ячейками.
extension GalleryViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: view.frame.width/3, height: view.frame.width/3) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 0 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 0 } }
Вот как выглядит конечный вариант.
Сегодня мы узнали:
- как создавать кастомные ячейки для ваших коллекций;
- как регистрировать ячейку;
- как отобразить ячейки;
- как менять размеры ячеек и отступы между ними.
До встречи на следующем Juniors Talks!
Ссылки полезные для прочтения:
- https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout;
- https://developer.apple.com/documentation/uikit/uicollectionview;
- https://www.raywenderlich.com/9334-uicollectionview-tutorial-getting-started;
- https://medium.com/@NickBabo/equally-spaced-uicollectionview-cells-6e60ce8d457b.