UICollectionView with two headers
You just need to use a simple trick.Show header and footer both for all sections.
In which section you do not want to show footer just pass its size zero as :--
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
if(section==0)
{
return CGSizeZero;
}
return CGSizeMake(320, 50);
}
Here I have used two sections like
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 2;
}
And passed no of rows in only one sections that is the last one as
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
if (section==1) {
return 20;
}
return 0;
}
And here is my output ---
Red View is header and Green One is footer.
Here u can get the entire Implementation File
How to setup a 1 header with multiple sections using UICollectionViewController
Here’s a simple implementation, that only overrides an optional method on the UICollectionViewDataSource protocol:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 3
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let section = indexPath.section
switch section {
case 0:
let TitleHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeHeaderReuseIdentifier, for: indexPath) as! TitleHeader
return TitleHeader
default:
let Section1Header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: sectionSpacingHeaderReuseIdentifier, for: indexPath) as! Section1Header
return Section1Header
}
case UICollectionElementKindSectionFooter:
let FooterView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: homeFooterReuseIdentifier, for: indexPath) as! FooterView
return FooterView
default:
return UICollectionReusableView()
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100.0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100.0)
}
UICollectionView with multiple sections
In these kind of scenarios, what you must be using is iOS 13's Compositional Layouts in CollectionView. Here are 2 tutorials for you to understand it -
- https://www.zealousweb.com/how-to-use-compositional-layout-in-collection-view/
- https://medium.com/better-programming/ios-13-compositional-layouts-in-collectionview-90a574b410b8
- WWDC video - https://developer.apple.com/videos/play/wwdc2019/215/
For your case, I've tweaked the example in the second tutorial
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (section == 0) ? 10 : 9
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print(indexPath)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: TimeSelectorCell.cellIdentifier, for: indexPath) as! TimeSelectorCell
return cell
}
private func commonInit() {
let cv = UICollectionView(frame: view.bounds, collectionViewLayout: createLayoutDiffSection())
cv.autoresizingMask = [.flexibleWidth, .flexibleHeight]
TimeSelectorCell.register(in: cv)
cv.dataSource = self
cv.delegate = self
addSubview(cv)
}
Till now, it is almost same as your code. Now the createLayoutDiffSection() method is -
func createLayoutDiffSection() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let seperateFlow = true
let columns = (sectionIndex == 0) ? 10 : 9
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 2, bottom: 0, trailing: 2)
let groupHeight = NSCollectionLayoutDimension.fractionalWidth(0.2)
let widthFraction:CGFloat = (sectionIndex == 0) ? 1 : 0.9
let groupSizeWidth:CGFloat = seperateFlow ? (widthFraction * 2) : 1
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(groupSizeWidth),
heightDimension: groupHeight)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: columns)
let section = NSCollectionLayoutSection(group: group)
if seperateFlow {
section.orthogonalScrollingBehavior = .continuous
}
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 0, bottom: 20, trailing: 0)
return section
}
return layout
}
If the scroll is not separate for both the sections, then set -
let seperateFlow = false
Important points here to understand are -
Size Classes
There are four size options that we can use according to our needs, and that will eliminate the need for the calculation to achieve the desired output. Let’s see all the size classes:
- fractionalWidth(): Using fractionalWidth we can set the width/height
of the cell proportional to its parent’s width - fractionalHeight():
Using fractionalHeight, we can set the width/height of the cell
proportional to its parent’s height - absolute(): Using absolute
value, we can set the width/height of the cell to a fixed value - estimate(): Using estimate value, we can set the cell’s width/height
according to the content size. The system will decide the optimal
width/height for the content.
Core Concepts
To build any compositional layout, the following four classes need to be implemented:
- NSCollectionLayoutSize — The width and height dimensions are of the
type NSCollectionLayoutDimension which can be defined by setting the
fractional width/height of the layout (percentage relative to its
container), or by setting the absolute or estimated sizes. - NSCollectionLayoutItem — This is your layout’s cell that renders on
the screen based on the size. - NSCollectionLayoutGroup — It holds the NSCollectionLayoutItem in either horizontal, vertical, or custom forms.
- NSCollectionLayoutSection — This is used to initialize the section by passing along the NSCollectionLayoutGroup. Sections eventually compose the compositional layouts.
How to create multiple Sections in UICollectionView with multiple Headers using RxDatasource
RxCollectionViewSectionedReloadDataSource<SectionModel>
expects that you will bind items of SectionModel
type, because you passed SectionModel
as a generic parameter. Apparently, you would like to use StudentModel
. To achieve this, you might make your StudentModel
conform to SectionModelType
protocol, and then use RxCollectionViewSectionedReloadDataSource<StudentModel>
:
extension StudentModel: SectionModelType {
// implement
}
let dataSource = RxCollectionViewSectionedReloadDataSource<StudentModel>(configureCell: { (datasource, collectionView, indexPath, element) in
// configure a cell
})
studentCells.bind(to: studentsView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag) // don't forget to setup disposal
But I suppose that StudentModel
is describing a single cell, rather than an entire section. Is such case, it may be a better idea to map StudentModel
to SectionModel
, like this:
let dataSource = RxCollectionViewSectionedReloadDataSource<SectionModel>(configureCell: { (datasource, collectionView, indexPath, element) in
// configure a cell
})
studentCells
.map { [SectionModel(model: "", items: $0)] }
.bind(to: studentsView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
Obviously, I mapped all your studentCells
into a single section, which might not be your case. In more complex scenarios, you might consider implementing a custom type conforming to SectionModelType
.
Also, you may pass something more valuable than an empty string as a model
, but again it depends on your needs.
Attension!
In an example above SectionModel
stands for RxDataSources.SectionModel
, not:
enum SectionModel {
case SectionOne(items: [SectionItem])
case SectionTwo(items: [SectionItem])
}
Multiple Section in UICollectionView
Make sure assigning DataSource & Delegate to CollectionView
1.Give number of sections you wanna show using below method
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 2
}
2.Set item count of each sections for CollectionView using below method.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (section == 0) ? list.count : list2.count
}
3.Assigning cell for each item to CollectionView.
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//If you are using multiple cells based on section make condition
if indexPath.section == 0 {
//make sure the identifier of your cell for first section
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath)
// do your stuffs
return cell
}else{
//make sure the identifier of your cell for second section
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath)
// do your stuffs
return cell
}
}
how to implement a uicollectionview that has multiple sections and subsections?
I've implemented this using UICollectionViewCompositionalLayout. Used theUICollectionViewCompositionalLayout { [self] (sectionNumber, environment) -> NSCollectionLayoutSection? in .... }
closure to setup the layout items and group them vertically and horizontally to form the layout for the entire section.
For reference -
To create an individual item (H: 50, W: 50) -
let item = NSCollectionLayoutItem(layoutSize: NSCollectionLayoutSize(widthDimension: .absolute(50), heightDimension: .absolute(50)))
To create groups (Horizontal) -
let group = NSCollectionLayoutGroup.horizontal(layoutSize:
NSCollectionLayoutSize(widthDimension:
.absolute(item.layoutSize.widthDimension.dimension * CGFloat((data.count))),
heightDimension: .estimated(50)), subitem: item, count: (data.count))
Group - vertical
let subGroup = NSCollectionLayoutGroup.vertical(layoutSize:
NSCollectionLayoutSize(widthDimension:
.absolute(CGFloat(width)),
heightDimension:
.absolute(heightForIndividualItem * CGFloat(data.count))),
subitems: group)
Collection View Multiple horizontal Section Header
This is working fine(here we are creating labels and buttons in collection view header
according to the figure) :-
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
CGFloat x=0,y=0;
for (int i = 0;i<[_officelist count];i++)
{
id val=[officeSize objectAtIndex:i];
CGFloat val1=[val floatValue];
UILabel *newLabel = [[UILabel alloc] initWithFrame:CGRectMake(x, 10,val1-1,35)];
newLabel.text=[NSString stringWithFormat:@"%@",_officelist[i]];
newLabel.textAlignment = NSTextAlignmentCenter;
newLabel.backgroundColor = [UIColor greenColor];
[self.roadmapCollectionView addSubview:newLabel];
x=x+val1+1;
}
for (int i=0; i<_departmentlist.count; i++) {
dept=[_departmentlist objectAtIndex:i];
id val=[officeSize objectAtIndex:i];
CGFloat val1=[val floatValue];
float val2=val1/[dept count];
//NSLog(@"DEPT SIZE - %f",val2);
for (int j = 0; j < [dept count]; j++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(y, 50,val2-1, 25);
[button setBackgroundColor:[UIColor yellowColor]];
[button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[button setTitle:[NSString stringWithFormat:@"%@",dept[j]] forState:UIControlStateNormal];
[self.roadmapCollectionView addSubview:button];
[deptSize addObject:[NSNumber numberWithFloat:y]];
y=y+val2+1;
}
}
return reusableView;
}
Having one Main sticky Header with Multiple Sections of UICollection views? Xcode - Swift
You can use collection view's collectionView:viewForSupplementaryElementOfKind:atIndexPath:
and if it is flow layout use also referenceSizeForHeaderInSection
Related Topics
How to Implement Localization in Swift Ui
How to Animate a Uiview with Constraints in Swift
Sqlite Database on Phonegap/iOS - More Than 5Mb Possible
Share Video on Twitter with Fabric API Without Composer iOS
Swift - Pushviewcontroller from Appdelegate, Rootviewcontroller.Navigationcontroller Is Nil
Does Nsthread Create Autoreleasepool Automatically Now
Full Resolution Screenshots for iPhone 6 and 6+
Add Inverted Circle Overlay to Map View
Difference Between Completion Handler and Blocks:[Ios]
How to Mock Ajax Call with Nsurlprotocol
Swift: Save Video from Nsurl to User Camera Roll
Container View Getting Pushed Down as If It Had a Uinavigationbar
Skspritenode Position in Universal Game
Orienting iOS Splash Image to Landscape/Portrait According to Launch Orientation
Alphabetical Sections in Table Table View in Swift
How to Move to the Next Page in Facebook JSON Response Using iOS Sdk