UICollectionView Несколько разделов и заголовков
Я пытаюсь сделать несколько разделов в моем представлении коллекции с заголовком для каждого раздела. Я не знаю Obj-C, и я нашел для него много учебников, но не смог понять, как преобразовать его в Swift.
Все мои данные являются статическими, поэтому мне нужен только какой-то массив или словарь, который я могу использовать для создания нескольких разделов. У меня уже есть представление коллекции с 1 секцией, поэтому, если у вас есть понимание или код для нескольких разделов, которые будут полезны.
Я знаю, как установить несколько разделов с помощью
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return sectionData.count
}
Я думаю, что главное, что мне нужно, это реализовать эту функцию
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { }
и настройки данных!
UICollectionView и UITableView почти одинаковы, поэтому, если вы знаете, как делать несколько разделов в UITableView в Swift, ваша помощь также оценивается
Ответы
Ответ 1
Функция cellForItemAtIndexPath
обрабатывает каждую секцию с помощью ячеек, она не обрабатывает разделы или дополнительные элементы управления, и, следовательно, это не главное, что вам нужно, когда речь заходит о создании заголовков разделов.
метод, который вам нужно реализовать, viewForSupplementaryElementOfKind
. Его подпись:
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {}
Предполагая, что ваш CollectionView работает правильно для 1 раздела (вы правильно заполнили тело cellForItemAtIndexPath, и ваш массив sectionData правильно отражает количество разделов, которые вы хотите отобразить), вы должны иметь возможность создавать заголовки секций, используя следующие указатели:
Наряду с ячейками UICollectionView
также поддерживает "дополнительные" объекты вида, обычно используемые для верхних или нижних колонтитулов. Эти дополнительные представления действуют очень похоже на объекты UICollectionViewCell
. Точно так же, как cellForItemAtIndexPath
обрабатывает ячейки, функция viewForSupplementaryElementOfKind
обрабатывает дополнительные представления.
Чтобы реализовать это, вам нужно сначала подготовить свой ViewController для этого. Сначала отредактируйте свой объект макета, чтобы отобразить соответствующий размер заголовка, который каждый заголовок будет придерживаться:
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.headerReferenceSize = CGSize(width: self.view.frame.size.width, height: 30)
ПРИМЕЧАНИЕ. Я использую UICollectionViewFlowLayout
Затем, если вы еще этого не сделали, создайте класс SectionHeader, который определяет объект заголовка каждого раздела, поэтому вы можете затем зарегистрировать этот класс с помощью объекта collectionView следующим образом:
collectionView!.registerClass(SectionHeaderView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "SectionHeaderView");
Здесь первый и третий приведенные аргументы совпадают с регистрацией класса UICollectionViewCell, первым аргументом в этом методе является ссылка на класс заголовка раздела, который вы создали. Третий - это идентификатор повторного использования для дополнительного просмотра.
Второй аргумент специфичен для дополнительных представлений, это задает вид дополнительного вида, который в этом случае является заголовком, для него используется константная строка, предоставленная классом UICollectionViewFlowLayout UICollectionElementKindSectionHeader
. Если вы заметили параметры в viewForSupplementaryElementOfKind
, этот вид позже передается как параметр kind: String
.
Заполните тело вашего viewForSupplementaryElementOfKind
так же, как и для функции cellForItemAtIndexPath. Используя метод dequeueReusableSupplementaryViewOfKind
для создания объекта SectionHeader, затем установите необходимые атрибуты (метки, цвета и т.д.) и наконец, вернуть объект заголовка.
Надеюсь, это поможет!
Ориентир:
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UICollectionViewDataSource_protocol/index.html#//apple_ref/occ/intfm/UICollectionViewDataSource/
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewFlowLayout_class/index.html#//apple_ref/c/data/UICollectionElementKindSectionHeade
Ответ 2
Вот код, который работал у меня
создать ячейку заголовка. Чтобы сделать то, что я создал пользовательский класс ячейки и наконечник, чтобы выполнить настройку ячейки в графическом редакторе
В viewDidLoad добавьте следующие
self.collectionView?.registerNib(UINib(nibName: "KlosetCollectionHeaderViewCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderCell")
Затем вы добавляете функцию делегата
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> KlosetCollectionHeaderViewCell {
let headerCell = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "HeaderCell", forIndexPath: indexPath) as? KlosetCollectionHeaderViewCell
return headerCell!
}
Это поместит HeaderCell в SectionView из PFCollectionView
Элементы управления, которые отображаются в ячейке, которую вы добавляете в файл xib, а также выходы и действия
Ответ 3
После создания и регистрации пользовательских заголовков (и/или нижних колонтитулов) вы можете легко указать разные заголовки (или, тем не менее, нижеследующие) для разных разделов. Вот пример:
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let section = indexPath.section
switch section {
case 0:
let userHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeHeaderReuseIdentifier, for: indexPath) as! UserHeader
return userHeader
default:
let postHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionSpacingHeaderReuseIdentifier, for: indexPath) as! PostHeader
return postHeader
}
case UICollectionElementKindSectionFooter:
let userFooter = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeFooterReuseIdentifier, for: indexPath) as! UserFooter
return userFooter
default:
return UICollectionReusableView()
}
}
Обязательно укажите правильное количество разделов:
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
Ответ 4
Готовое решение для Swift-3
i) Создать пользовательскую ячейку && соответствующий xib
class SectionHeaderView: UICollectionViewCell {
static let kReuseIdentifier = "SectionHeaderView"
@IBOutlet weak var invitationsSectionHeader: UILabel!
@IBOutlet weak var numberOfPerson: UILabel!
}
ii) Регистрация ячейки коллекции пользовательской коллекции для HeaderView
self.collectionView.register(UINib(nibName: SectionHeaderView.kReuseIdentifier, bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeaderView.kReuseIdentifier)
iii) Вызовите функцию делегата для визуализации представления пользовательского заголовка.
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView: SectionHeaderView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeaderView.kReuseIdentifier, for: indexPath) as! SectionHeaderView
return headerView
default:
return UICollectionReusableView()
}
}
iv) Упоминание высоты пользовательского представления заголовка
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width:collectionView.frame.size.width, height:30)
}
Ответ 5
Определите свой UICollectionViewCell, который будет вашим видом заголовка вида UICollectionElementKindSectionHeader. В моем случае у меня есть два заголовка: OfferHeaderCell и APRHeaderCell, как указано ниже:
verticalCollectionView.register(UINib(nibName: "OfferHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "OfferHeaderCell")
verticalCollectionView.register(UINib(nibName: "APRHeaderCell", bundle: nil), forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "APRHeaderCell")
Идем дальше и возвращаем заголовок для каждого раздела, а затем устанавливаем размер заголовка раздела, чтобы иметь нулевой размер в этой функции UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if(section==0) {
return CGSize.zero
} else if (section==1) {
return CGSize(width:collectionView.frame.size.width, height:133)
} else {
return CGSize(width:collectionView.frame.size.width, height:100)
}
}
Важно определить viewForSupplementaryElementOfKind для двух разных разделов, как показано ниже:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var reusableview = UICollectionReusableView()
if (kind == UICollectionElementKindSectionHeader) {
let section = indexPath.section
switch (section) {
case 1:
let firstheader: OfferHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "OfferHeaderCell", for: indexPath) as! OfferHeaderCell
reusableview = firstheader
case 2:
let secondHeader: APRHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "APRHeaderCell", for: indexPath) as! APRHeaderCell
reusableview = secondHeader
default:
return reusableview
}
}
return reusableview
}
И, наконец, Datasource,
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (section==2) {
return 2
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = verticalCollectionView.dequeueReusableCell(withReuseIdentifier: "ReviseOfferCell", for: indexPath)
cell.backgroundColor = UIColor.white
return cell
}
Примечание. Не забудьте добавить UICollectionFlowLayout, как показано ниже:
//MARK: UICollectionViewDelegateFlowLayout
extension MakeAnOfferController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if indexPath.item == 0 {
return CGSize(width: self.view.frame.size.width, height: 626.0)
}
return CGSize()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if(section==0) {
return CGSize.zero
} else if (section==1) {
return CGSize(width:collectionView.frame.size.width, height:133)
} else {
return CGSize(width:collectionView.frame.size.width, height:100)
}
}
}