How to scroll the collection view horizontal with header - ios

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

Related

Why my UICollectionView doesn't scroll to the last item of my list?

I have a UICollectionView with a horizontal scroll that shows 3 cells for each page but when I get to the last page there is only one element and it does not let me scroll to show this last element.
This is my list:
var benefitIcons = ["ic_benefit_frappe", "ic_benefit_birthday", "ic_benefit_2x1", "ic_benefit_points", "ic_benefit_combo", "ic_benefit_cine", "ic_benefit_tickets", "ic_benefit_refill", "ic_benefit_klic", "ic_benefit_pay"]
This is the method for UICollectionView:
extension ProfileCCViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return benefitIcons.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = benefitCollection.dequeueReusableCell(withReuseIdentifier: "BenefitCell", for: indexPath) as? UserBenefitsCell {
cell.benefitIcon.image = UIImage(named: benefitIcons[indexPath.row])
cell.benefitLbl.text = benefitDescriptions[indexPath.row]
return cell
} else {
return UICollectionViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.bounds.width/3, height: collectionView.bounds.height)
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
benefitControl.currentPage = indexPath.row
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offSet = scrollView.contentOffset.x
let width = scrollView.frame.width
let horizontalCenter = width / 2
benefitControl.currentPage = Int(offSet + horizontalCenter) / Int(width)
}
}
This how look like correctly:
But when I'm scrolling to the last item and is uneven doesn't scroll to this last section:

DidSelect a cell in Collection View implemented in Collection View cell

Have an issue with collection view cell.
i've got a collection view (vertical scroll) with 2 sections (1st is ServiceCell and the 2nd is OfferCell as ). First section is with 1 item - another collection view that is set in class ServiceCell: UIcollectionViewCell {} (horizontal scroll) with multiply subcells (ServiceSubCell).
i can't understand where i have to implement didselect method for subcells
main view conroller looks like this:
extension HomeScreenViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSections(in collectionView: UICollectionView) -> Int {
2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == 0 {
return 1
}
return offers.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.section == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ServiceCell.reuseId, for: indexPath) as! ServiceCell
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: OfferCellSubCell.reuseId, for: indexPath) as! OfferCellSubCell
cell.backgroundColor = .white.withAlphaComponent(0.6)
cell.layer.cornerRadius = 20
cell.setup(with: offers[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.section == 0 {
// this part doesn't work
let serviceVC = ServiceScreenViewController() as ServiceScreenViewController
serviceVC.category = servicesCategoriesArray[indexPath.row]
self.navigationController?.pushViewController(serviceVC, animated: true)
} else {
let offerVC = OfferScreenViewController() as OfferScreenViewController
offerVC.offerNew = offers[indexPath.row]
self.navigationController?.pushViewController(offerVC, animated: true)
}
}
}
Service cell with extension
class ServiceCell: UICollectionViewCell, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return servicesCategoriesArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ServiceCellSubCell.reuseId, for: indexPath) as! ServiceCellSubCell
cell.setup(with: servicesCategoriesArray[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 140, height: 140)
}
}
You should implement "didSelect" in ServiceCell
and you should implement in your ViewController "should highlight" for first section to "false"
func collectionView(_ collectionView: UICollectionView,
shouldHighlightItemAt indexPath: IndexPath) -> Bool {
return yourServiceSection ? false : true
}
the below code must be in ServiceCell and ViewController
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionview.deselectItem(at: indexPath, animated: true)
}
in your "ServiceCell" you must add this extension:
import Foundation
import UIKit
extension ServiceCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.list.count ?? 0
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
ServiceSubCell.nameOfClass,
for: indexPath) as? ServiceSubCell
if let item = viewModel.data?.item(at: indexPath.item) {
cell?.config(item: item)
}
return cell ?? UICollectionViewCell()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: SizeConstant.ServiceSubCellWidth.rawValue,
height: SizeConstant.ServiceSubCellHeight.rawValue)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionview.deselectItem(at: indexPath, animated: true)
// implement your code you need
}
}

CollectionView is not displaying vertically as expected

I am trying to implement following screen.
But in my code, it is displaying following way
following code I wrote,
import UIKit
class LunchViewController: UIViewController {
#IBOutlet weak var mainCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension LunchViewController:UICollectionViewDataSource,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 412, height: 180)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return self.myLibraryArray.count
return 8
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// let item = self.myLibraryArray[indexPath.row]
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RestaurantCollectionViewCell", for: indexPath) as? RestaurantCollectionViewCell else {
return UICollectionViewCell()
}
//cell.fillDetails(item)
return cell
}
}
Here is the complete project link
Can any one tell me, what is the issue? or what I have to write the code to get expected output?
Update:
Select collectionView and Change Estimate Size to none. In storyboard.
if you dont want space between two cells then set 0 to for lines in Min spacing
And i have given width as screen width
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: UIScreen.main.bounds.size.width, height: 180)
}
Output :-
Change sizeForItem method to this:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.size.width, height: 180)
}
Also, make sure the mainCollectionView is constrained to the leading and trailing edges in the storyboard.

UICollectionViewController Footer/ Header not showing

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 {

UIcollectionview cell issue Swift

I have a simple collectionview controller like this:
class ViewController1: UICollectionViewController{
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.delegate = self
self.collectionView?.dataSource = self
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "P", for: indexPath)
return cell
}
}
In the cell there is only an uiimageview and it has this constraints:
My problem is this:
when I execute this code on iPhone 6 simulator I get this (right way):
but when I execute this code on iPhone 5 simulator I get this (wrong way: the imageview starts before the screen on the left and the width and height are wrong respect to the constraints):
I am going crazy for this problem but I dont be able to solve.
Can you help me?
You need to extend your ViewController1 to conform to UICollectionViewDelegateFlowLayout protocol. And implement methods to set size for each collection view cell like so:
class ViewController1: UICollectionViewController, UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView?.delegate = self
self.collectionView?.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(self.collectionView!.frame)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "P", for: indexPath)
return cell
}
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 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.collectionView!.frame.size.width, height: 120.0)
}
}
It has hard coded values, but you should get the idea. Collection View width should be the max size for each item, so they won't get outside the box.

Resources