Using UICollectionView, we implement screens with multiple sections.
We use UICollectionViewFlowLayout customized to make cell sizes variable.
To display the header, the recognition is to set the following values when you generate the layout:
let layout=UICollectionViewFlowLayout()
layout.headerReferenceSize=CGSizeMake(10,10)
By configuring the above, the following functions are known:
func collectionView(collectionView:UICollectionView, viewForSupplementaryElementOfKind:String, atIndexPathindexPath:NSIndexPath)->UICollectionReusableView{}
When using custom classes for layout as follows, the above functions are no longer called.
let layout=CustomLayout()
layout.headerReferenceSize=CGSizeMake(10,10)
Is there any reason why the headerReferenceSize value has been cleared somewhere?
ViewController.swift
var myCollectionView:UICollectionView!
var mySection: [String] = ["Section 1", "Section 2" ]
override func viewDidLoad(){
super.viewDidLoad()
let layout = CustomLayout()
// Header Size by Section
layout.headerReferenceSize=CGSizeMake(self.view.frame.width,100)
layout.sectionInset=UIedgeInsetsMake(8,8,8,8)
layout.minimumLineSpacing=8
layout.minimumInteritemSpacing=8
layout.maxColumn = 5
layout.cellPattern.append ((sideLength:2, heightLength:2, column:0, row:0))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:2, row:0))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:3, row:0))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:4, row:0))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:2, row:1))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:3, row:1))
layout.cellPattern.append ((sideLength:1, heightLength:1, column:4, row:1))
myCollectionView=UICollectionView(frame:self.view.frame, collectionViewLayout:layout)
myCollectionView.registerClass(CustomUICollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.registerClass(CustomCollectionReusableView.self, forSupplementaryViewOfKind:UICollectionElementKindSectionHeader, withReuseIdentifier: "MySection")
myCollectionView.delegate=self
myCollectionView.dataSource=self
self.view.addSubview(myCollectionView)
}
override funcdidReceiveMemoryWarning(){
super.didReceiveMemoryWarning()
}
func numberOfSectionsInCollectionView (collectionView:UICollectionView) - > Int {
return mySection.count
}
functioncollectionView(collectionView:UICollectionView, didSelectItemAtIndexPathindexPath:NSIndexPath){
print ("Cell Press")
}
functioncollectionView (collectionView:UICollectionView, numberOfItemsInSection section:Int) - > Int {
switch(section){
case0:
return7
case1:
return7
default:
return 0
}
}
func collectionView (collectionView:UICollectionView, viewForSupplementaryElementOfKindkind: String, atIndexPathindexPath:NSIndexPath)->UICollectionReusableView{
letheaderView: CustomCollectionReusableView=collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "MySection", forIndexPath:indexPath) as!CustomCollectionReusableView
headerView.title?.text=mySection [indexPath.section]
return headerView
}
functioncollectionView (collectionView:UICollectionView, cellForItemAtIndexPathindexPath:NSIndexPath) - >UICollectionViewCell{
letcell:CustomUICollectionViewCell=collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath:indexPath)as!CustomUICollectionViewCell
switch(indexPath.section){
case0:
cell.backgroundColor=UIColor.redColor()
cell.textLabel?.text="0"
cell.imageTest.image=UIImage(named: "image01.jpg")
case1:
cell.backgroundColor=UIColor.greenColor()
cell.textLabel?.text="1"
default:
print("section error")
cell.backgroundColor=UIColor.whiteColor()
}
return cell
}
CustomUICollectionViewCell.swift
var textLabel:UILabel!
varimageTest —UIImageView!
required init?(coder adecoder:NSCoder) {
super.init(coder:aDecoder)
}
override init (frame:CGRect) {
super.init (frame:frame)
textLabel = UILabel (frame: CGRectMake (0,0, frame.width, frame.height))
textLabel?.text="nil"
textLabel?.textAlignment=NSTextAlignment.Center
imageTest = UIImageView (frame: CGRectMake(0,0, frame.width, frame.height))
self.contentView.addSubview(imageTest)
self.contentView.addSubview(textLabel)
}
CustomLayout.swift
private staticlet maxRow=3
var maxColumn = maxRow
varcellPattern: [(sideLength: CGFloat, heightLength: CGFloat, column: CGFloat, row: CGFloat)] = [ ]
private var sectionCells=[[CGRect]]()
private var contentSize = CGSizeZero
override func prepareLayout() {
super.prepareLayout()
sectionCells=[CGRect]()
iflet collectionView =self.collectionView {
contentSize = CGSize (width: collectionView.bounds.width-collectionView.contentInset.left-collectionView.contentInset.right, height:0)
let smallCellSideLength: CGFloat=(contentSize.width-super.sectionInset.left-super.sectionInset.right-(super.minimumInteritemSpacing*(CGFloat(maxColumn)-1.0))/ CGFloat(maxColumn)
for section in (0..<collectionView.numberOfSections()) {
varcells= [CGRect]()
let numberOfCellInSection=collectionView.numberOfItemsInSection(section)
var height = contentSize.height
for in(0..<numberOfCellInSection){
let position = i% (numberOfCellInSection)
let cellPosition=position%cellPattern.count
letcell=cellPattern [cellPosition]
letx=(cell.column*(smallCellSideLength+super.minimumInteritemSpacing)) + super.sectionInset.left
letty=(cell.row*(smallCellSideLength+super.minimumLineSpacing))+contentSize.height+super.sectionInset.top
let cellwidth=(cell.sideLength*smallCellSideLength)+(cell.sideLength-1)*super.minimumInteritemSpacing)
let cellheight=(cell.heightLength*smallCellSideLength)+(cell.heightLength-1)*super.minimumInteritemSpacing)
let cellRect=CGRectMake(x,y,cellwidth,cellheight)
cells.append(cellRect)
if(height<cellRect.origin.y+cellRect.height){
height = cellRect.origin.y + cellRect.height
}
}
contentSize = CGSize (width: contentSize.width, height:height)
sectionCells.append(cells)
}
}
}
override funclayoutAttributesForElementsInRect(rect:CGRect)->[UICollectionViewLayoutAttributes]?{
var layoutAttributes = UICollectionViewLayoutAttributes()
iflet collectionView =self.collectionView {
for in(0..<collectionView.numberOfSections()){
let numberOfCellsInSection=collectionView.numberOfItemsInSection(i)
for jin(0..<numberOfCellsInSection){
let indexPath = NSIndexPath (forRow:j, inSection:i)
iflet attributes=layoutAttributesForItemAtIndexPath(indexPath){
if(CGRectIntersectsRect(rect, attributes.frame)){
layoutAttributes.append(attributes)
}
}
}
}
}
return layoutAttributes
}
override funclayoutAttributesForItemAtIndexPath(indexPath:NSIndexPath)->UICollectionViewLayoutAttributes?{
let attributes=super.layoutAttributesForItemAtIndexPath(indexPath)
attributes!.frame=sectionCells [indexPath.section] [indexPath.row]
return attributes
}
override func collectionViewContentSize()->CGSize{
return contentSize
}
CustomCollectionReusableView.swift
vartitle: UILabel!
varbackgroundImage:UIImageView!
required init?(coder adecoder:NSCoder) {
super.init(coder:aDecoder)
}
override init (frame:CGRect) {
super.init (frame:frame)
title=UILabel(frame:CGRectMake(frame.width*0.05,0, frame.width, frame.height))
title.text="nil"
title.textAlignment=NSTextAlignment.Left
title.textColor=UIColor.redColor()
let bgImage: UIImage=UIImage(named: "image02.jpg")!
backgroundImage=UIImageView (frame: CGRectMake(0,0, frame.width, frame.height))
backgroundImage.image=bgImage
self.addSubview(backgroundImage)
self.addSubview(title)
}
Have you read this document carefully?
Collection View Programming Guide
(HTML's English version may be easier to read than the Japanese version of pdf.)
here:
(From scenario in Table 3-1: I want to add a new auxiliary or decorative view)
The standard 」flow layout は class can only add section headers and section footers as auxiliary views and does not support decorative views.If you want to add an auxiliary or decorative view, you must override at least the following methods:
layoutAttributesForElementsInRect:
(required)layoutAttributesForItemAtIndexPath:
(required)layoutAttributesForSupplementaryViewOfKind:atIndexPath:
(for auxiliary view)layoutAttributesForDecorationViewOfKind:atIndexPath:
(for Decorative View)In your case, you are trying to define a header that is an auxiliary view, so you need to implement the following three methods correctly:
layoutAttributesForElementsInRect:
layoutAttributesForItemAtIndexPath:
layoutAttributesForSupplementaryViewOfKind:atIndexPath:
(*1) Above, override is required (you need to override), but in this case, since it is not new, the behavior defined in UICollectionViewFlowLayout
may still work.
In your code, you notice a problem with the implementation of layoutAttributesForElementsInRect(_:)
.
The layoutAttributesForElementsInRect:
method calls super
to retrieve cell layout attributes and add attributes for new auxiliary or decorative views to place in the specified rectangle.Other methods have the ability to specify attributes as needed.
(The above text doesn't seem to be a good thing to look at, so I recommend you to read the original text.)
In your layoutAttributesForElementsInRect:
method, you can call super
to get the layout attributes for the cells and then the attributes for any new supplementary or determination views that are in the specified reorder. Together.
(Practical translation of the last sentence: Use other methods to provide attributes if necessary.)
The key to this topic is that layoutAttributesForElementsInRect(_:)
also requires you to return the layout attributes for auxiliary and decorative views.
Your code layoutAttributesForElementsInRect(_:)
only tries to return layout attributes for cells, so as a result collectionView(_:viewForSupplementaryElementOfKind:indexPath:)
is not called either.
Try modifying the above methods, for example:
override funclayoutAttributesForElementsInRect(rect:CGRect)->[UICollectionViewLayoutAttributes]?{
var layoutAttributes = UICollectionViewLayoutAttributes()
iflet collectionView =self.collectionView {
for in 0..<collectionView.numberOfSections(){
let numberOfCellsInSection=collectionView.numberOfItemsInSection(i)
for jin0..<numberOfCellsInSection{
let indexPath = NSIndexPath (forRow:j, inSection:i)
iflet attributes=layoutAttributesForItemAtIndexPath(indexPath){
if(CGRectIntersectsRect(rect, attributes.frame)){
layoutAttributes.append(attributes)
}
}
// You must also return layout attributes for auxiliary and decorative views
// Header and footer for UICollectionViewFlowLayout (both auxiliary views)
iflet attributes=layoutAttributesForSupplementaryViewOfKind (UICollectionElementKindSectionHeader, atIndexPath:indexPath) {
if CGRectIntersectsRect(rect, attributes.frame) {
layoutAttributes.append(attributes)
}
}
iflet attributes=layoutAttributesForSupplementaryViewOfKind (UICollectionElementKindSectionFooter, atIndexPath:indexPath) {
if CGRectIntersectsRect(rect, attributes.frame) {
layoutAttributes.append(attributes)
}
}
}
}
}
return layoutAttributes
}
At the very least, you should be able to resolve the above function (collectionView(_:viewForSupplementaryElementOfKind:indexPath:)
) that is no longer calledTry it.
© 2024 OneMinuteCode. All rights reserved.