I am implementing a one section UICollectionViewController where I would like to add a header & footer.
I have read RayWenderlich tutorial to implement the logic and everything works fine EXCEPT my header & footer which are not showing up.
I checked "Section Header" & "Section Footer" in storyboard inspector, and added identifier for each UICollectionReusableView with "headerView" and "footerView".
I implemented the viewForSupplementaryElementOfKind method (see below code), but is not triggered (no breakpoints fired while debugging) while referenceSizeForFooterInSection and referenceSizeForHeaderInSection are . When app launch, I can't see header and footer background color, however I can see a space which should be header & footer.
Thank you in advance!
Here is an extract from my ViewController:
class VoteNextCityViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {
fileprivate let sectionInsets = UIEdgeInsets(top: 50.0, left: 20.0, bottom: 50.0, right: 20.0)
fileprivate let itemsPerRow: CGFloat = 2
private let cellID = "cellID"
var pendingCityArray: [City] = []
override func viewDidLoad() {
super.viewDidLoad()
fetchVotedCities()
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! VoteNextCityCell
let city = pendingCityArray[indexPath.row] //cannot not be nil, else numberOfItemsInSection would return 0
cell.setupView(city: city)
return cell
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pendingCityArray.count
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
//2
let paddingSpace = sectionInsets.left * (itemsPerRow + 1)
let availableWidth = view.frame.width - paddingSpace
let widthPerItem = availableWidth / itemsPerRow
return CGSize(width: widthPerItem, height: widthPerItem+50)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets {
return sectionInsets
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return sectionInsets.left
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
return CGSize(width: (self.collectionView?.frame.size.width)!, height: 50)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: (self.collectionView?.frame.size.width)!, height: 50)
}
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionFooter :
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "footerView", for: indexPath as IndexPath)
view.backgroundColor = UIColor.blue
return view
case UICollectionElementKindSectionHeader:
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath as IndexPath)
view.backgroundColor = UIColor.red
return view
default:
assert(false, "Unexpected element kind")
}
}
I think only the _ (underscore with a space) is missing as per new syntax.
So try replacing the function definition
func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
with the below one
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
Related
I'm trying to make images grid like the below image
I tried the below code
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionViw: UICollectionView!
var widthss = [59.0,59.0,59.0,121.0,59.0,59.0,59.0,59.0,59.0,59.0,28.0,28.0,59.0,59.0,] as [CGFloat]
var heights = [36.0,36.0,36.0,76.0,36.0,76.0,36.0,36.0,36.0,76.0,36.0,36.0,36.0,76.0,] as [CGFloat]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return heights.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! UICustomCollectionViewCell
// Customize cell height
cell.frame = CGRect(x: cell.frame.origin.x, y: cell.frame.origin.y , width: widthss[indexPath.row], height: heights[indexPath.row])
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: widthss[indexPath.row], height: heights[indexPath.row])
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}}
at the end, i found the result like the below image,
what I need is to make the collection view cells like the first image
Anyone have an idea where is my mistake
thanks in advance
I'm currently trying to set spacing between my collection view cells. The issue is every time I scroll horizontally the cell does not reset back to where is should be. I'm using this library for the collection view cell animation: https://github.com/KelvinJin/AnimatedCollectionViewLayout.
Please Look at image bellow!
Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Turn on the paging mode for auto snaping support.
collectionView?.isPagingEnabled = true
if let layout = collectionView?.collectionViewLayout as? AnimatedCollectionViewLayout {
layout.scrollDirection = direction
layout.animator = animator?.0
}
dismissGesture.direction = direction == .horizontal ? .down : .left
}
extension ImageCollectionViewController: UICollectionViewDelegateFlowLayout {
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int(Int16.max)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let c = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
if let cell = c as? SimpleCollectionViewCell {
let i = indexPath.row % vcs.count
let v = vcs[i]
cell.bind(color: v.0, imageName: v.1)
cell.clipsToBounds = animator?.1 ?? true
}
return c
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
guard let animator = animator else { return view.bounds.size }
return CGSize(width: view.bounds.width / CGFloat(animator.2), height: view.bounds.height / CGFloat(animator.3))
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return .zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
Also here are images showing what happens:
I have collectionview with header.
This is the image
In this, i have display the questions in the UICollectionReusableView as header and answers in the collectionviewcell.
So the image is this way.But i need to scroll the collectionview horizontal only.
But that time it will become as :-
This is the header.
This is the cell.
But i need this in the first screen header and its answers. when user scroll it then need show 2nd question in header and its answers. How to implement it?
currently my code is as below:-
extension NH_DummyDataViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return self.questionViewModel.numberOfSections()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.questionViewModel.numberOfRowsIn(section: section)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = verticalCollectionView.dequeueReusableCell(withReuseIdentifier: "NH_Headercell", for: indexPath)as! NH_Headercell
// cell.options.text = "hello"
// let optionModel = self.questionViewModel.datafordisplay(atindex: indexPath)
cell.setReviewData(reviews:self.questionViewModel.datafordisplay(atindex: indexPath))
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let firstheader: NH_QuestionHeaderCell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "NH_QuestionHeaderCell", for: indexPath ) as! NH_QuestionHeaderCell
firstheader.setReviewData(reviews:questionViewModel.titleForHeaderInSection(atsection:indexPath.section))
return firstheader
}
}
// MARK: UICollectionViewDelegateFlowLayout
extension NH_DummyDataViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: collectionView.frame.width, height: 100)
}
}
Set Collection view scroll direction Horizontal and set paging
yourCollectionview.pagingEnabled = true
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionViewWidth = collectionView.bounds.width
let keys = Array(indoordataDictionary.keys)
let keyString:String = keys[indexPath.section]
let objFacilityUserList:FacilityUserList = indoordataDictionary[keyString]! as! FacilityUserList
if objFacilityUserList.facilityUserList.count == 1 {
return CGSize(width: collectionViewWidth, height: 30)
}
return CGSize(width: collectionViewWidth/2, height: 70)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if indoorSegment.selectedSegmentIndex == 1 {
return CGSize(width:collectionView.frame.size.width, height:0.0)
}
else {
return CGSize(width:collectionView.frame.size.width, height:40.0)
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let headerView: PlaceCollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TagIDConstant.nibs.kPlaceCollectionReusableViewID, for: indexPath) as! PlaceCollectionReusableView
let keys = Array(indoordataDictionary.keys)
let keyString:String = keys[indexPath.section]
headerView.placeNameLabel.text = keyString
return headerView
}
If you are using the Custom Layout for the CollectionView then the following link is the best class for that, which will solve this Section Header overlapping problem.
https://gist.github.com/olxios/9e0ae85d49529b0d8b8a6fe6e7a00fab
Hope it helps to those who are using the Custom Layout for the CollectionView.
i am using collectionview to show image in full screen and allowing scrolling between different images. but when orientation will change it's not showing properly..And this is my code
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
// collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()
if visibleCell != nil {
collectionView.selectItem(at: visibleCell as IndexPath?, animated: true, scrollPosition: .centeredHorizontally)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCell", for: indexPath) as! ImageCollectionViewCell
print(cell.frame)
cell.SectionImage.image = images[indexPath.row].image
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.view.frame.width, height: self.view.frame.height)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
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
}
Use UICollectionView sizeForItemAtIndexPath method to define height and width of cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let leftAndRightPaddings: CGFloat = 15.0
let numberOfItemsPerRow: CGFloat = CGFloat(NUMBER_OF_ITEMS_PER_ROW)
let bounds = UIScreen.mainScreen().bounds
let width = (bounds.size.width - leftAndRightPaddings * (numberOfItemsPerRow+1)) / numberOfItemsPerRow
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSizeMake(width, width)
return layout.itemSize
}
Try it. And you will get your expected result.
First of all set the minimum spacing for cell and lines to 0.
After that return the size of cell equal to UICollectionView by using the delegate method
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
return CGSizeMake(collectionView.frame.size.width, collectionView.frame.size.height)
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
dispatch_async(dispatch_get_main_queue()) {
self.collectionView.reloadData()
}
print_debug("change orientation")
}
Its work for me in the same situation.