#swift #xcode #uicollectionview #uibezierpath #uicollectionviewcompositionallayout
Вопрос:
Я создаю приложение для коллажей, для которого я буду использовать несколько макетов сетки.Я использую UICollectionViewCompositionalLayout для создания сеток. Для одной из моих сеток требуется ячейка в форме сердца между ними. Ниже приведен мой код, элемент в форме сердца должен быть в форме сердца, я понятия не имею, как это сделать, сначала я подумал об использовании UIBeizerPath, но элемент не относится к типу слоя, и если мне каким-то образом удастся сделать это внутри cellForItem, все равно у меня будет еще много сеток, и мне придется снова и снова использовать «если», «иначе». Еще одна проблема, с которой я столкнулся в своей последней группе, т. е. нижняя группа не отображается.
Любая помощь была бы очень признательна.
let topItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalHeight(1)))
// top items group
let topGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1/4)), subitem: topItem, count: 3)
topGroup.contentInsets = .init(top: 0, leading: 3, bottom: 0, trailing: 3)
topGroup.interItemSpacing = .fixed(2)
// middle right item
let middleRightItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/4), heightDimension: .fractionalHeight(1)))
// middle left item
let middleLeftItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/4), heightDimension: .fractionalHeight(1)))
// Heart Shaped
let heartShapedItem = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/2), heightDimension: .fractionalHeight(1)))
// middle three items group
let middleGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1/3)), subitems: [middleRightItem,heartShapedItem,middleLeftItem])
middleGroup.contentInsets = .init(top: 0, leading: 3, bottom: 0, trailing: 3)
middleGroup.interItemSpacing = .fixed(2)
// bottom three items group
let bottomGroup = NSCollectionLayoutGroup.horizontal(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1/4)), subitem: topItem, count: 3)
let finalGroup = NSCollectionLayoutGroup.vertical(layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1)), subitems: [topGroup,middleGroup,bottomGroup])
finalGroup.interItemSpacing = .fixed(2)
let section = NSCollectionLayoutSection(group: finalGroup)
return section
Ответ №1:
Макет представления коллекции определяет визуальное расположение содержимого в вашей коллекции — таким образом, UICollectionViewCompositionalLayout
вы указываете в своем представлении коллекции такие параметры, как количество элементов в строке, размеры и смещения, поведение ортогональной прокрутки, заголовки и элементы оформления, а не то, как выглядит определенная ячейка.
В cellForItem
вы можете настроить свои ячейки, включая их слои, — вы можете изменять формы там. Ячейки будут расположены в представлении коллекции на основе ваших параметров UICollectionViewCompositionalLayout
.
Если вы используете UICollectionViewDiffableDataSource
, вы можете различать различные типы ячеек (т. Е. Ячейки в форме сердца и круга) с помощью следующего примера кода:
func configureDataSource() {
dataSource = DataSource(collectionView: collectionView) { [self] (collectionView: UICollectionView, indexPath: IndexPath, item: ViewCell) -> UICollectionViewCell? in
switch item.type {
case .heart: return hearCell(for: indexPath)
case .circle: return circleCell(for: indexPath)
default: return normalCell(for: indexPath)
}
}
}
В пользовательской ячейке просмотра структуры у меня есть перечисление для типа ячейки:
struct ViewCell: Hashable {
var tag: Int
var type: CellType
}
enum CellType { case heart, circle }
Что касается проблемы с нижней группой — достаточно ли у вас элементов в представлении коллекции, чтобы заполнить все группы?
Обновить:
Проблема в вашем макете связана с этой строкой:
middleGroup.interItemSpacing = .fixed(2)
При этом 3 ряда в средней группе не могут быть помещены в один ряд. Вы можете удалить его и добиться такого же расстояния, добавив вставки в средний элемент:
heartShapedItem.contentInsets = .init(top: 0, leading: 2, bottom: 0, trailing: 2)
Поскольку вы не используете UICollectionViewDiffableDataSource
, вы можете дифференцировать свои клетки по indexPath. Таким образом, если у вас есть только 1 раздел, ваш элемент HEARTshape будет иметь indexPath.строка из 4:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.reuseID, for: indexPath) as? MyCollectionViewCell else { return UICollectionViewCell() }
cell.label.text = "(indexPath.row)"
cell.label.textAlignment = .center
cell.backgroundColor = .green
if indexPath == IndexPath(row: 4, section: 0) {
cell.label.text = "HEART"
}
return cell
}
(в вашем исходном коде нет интервала между элементами в нижней группе, я не знаю, было ли это сделано намеренно или нет)
Комментарии:
1. да, у меня достаточно всего, что я использую topitem дважды
2. можете ли вы сказать мне, как я могу использовать перечисление с помощью UICollectionViewКомпозиционноЕотказ извините, я еще не очень хорошо разбираюсь в swift, если хотите, я могу поделиться своим кодом для flowlayout
3. UICollectionViewCompositionalLayout может использоваться либо с UICollectionViewDataSource (который вы используете), либо с UICollectionViewDiffableDataSource (который я предлагаю использовать). Перечисление, которое я показал в своем ответе, является частью UICollectionViewDiffableDataSource и позволяет дифференцировать ячейки не только по indexPath (как в вашем случае с CollectionView(_:cellForItemAt:)), но и с помощью пользовательского элемента. Пользовательский элемент может иметь столько свойств, сколько вам нужно, включая перечисление для типа ячейки.
4. Источник данных = UICollectionViewDiffableDataSource<Раздел,модель изображения>(Представление коллекции: Представление коллекции!) { [self] (CollectionView, indexPath, изображение) -> CollectionViewCell Это мой источник diffabledatasource Я действительно запутался в том, как использовать перечисление извините за беспокойство, но у меня мало опыта работы со swift. Мне понравилось, как работает diffable, теперь я изменил свой код на diffable, но все еще не уверен, как получить доступ к элементу с помощью перечисления.
5. Большое вам спасибо, Виктор, это было не совсем то, что я хотел сделать, но вы очень приблизили меня к тому, что я хотел сделать, и я сделал это с вашей помощью