UICollectionViewFlowLayout one row/section horizontal - ios

I have seen so many ways to get a carousel/one row/section in UICollectionView. But non is working probably, do you have a way.
I have the following:
#IBAction func openCollectionView(_ sender: Any) {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.itemSize = CGSize(width: 50, height: self.view.frame.height)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView!.delegate = self
collectionView!.dataSource = self
collectionView!.register(PDCollectionViewCell.self, forCellWithReuseIdentifier: "cellIdentifier")
collectionView?.contentOffset.x = 20
collectionView?.reloadData()
collectionView?.layoutIfNeeded()
collectionView!.addBlurEffect()
self.view.addSubview(collectionView!)
}

Ok - simple enough:
layout.itemSize = CGSize(width: (self.view.frame.size.width/2)+50, height: (self.view.frame.size.height/2)+50)
And for more complex cells:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: 100, height: 100)
}

Related

Create cell dynamic width UICollectionViewCell

I have a problem with UICollectionViewCell.
How can I make the cell width the same on all screens?
on iPhone 13pro max, everything looks great
on iPhone se, cells in one line
Here I configure collectionView
private func makeCollectionView() -> UICollectionView {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: 190, height: 174)
layout.sectionInset = UIEdgeInsets(top: 20, left: 8, bottom: 16, right: 8)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(MenuCollectionViewCell.self, forCellWithReuseIdentifier: MenuCollectionViewCell.reuseIdentifer)
collectionView.backgroundColor = .clear
collectionView.dataSource = self
collectionView.delegate = self
collectionView.isScrollEnabled = false
collectionView.showsVerticalScrollIndicator = false
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}
How can I implement one size for all screens?
I solved the problem!
I did not calculate the cell size correctly.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let flowayout = collectionViewLayout as? UICollectionViewFlowLayout
let space: CGFloat = (flowayout?.minimumInteritemSpacing ?? 0.0) + (flowayout?.sectionInset.left ?? 0.0) + (flowayout?.sectionInset.right ?? 0.0)
let size: CGFloat = (collectionView.frame.size.width - space) / 2.0
return CGSize(width: size, height: size)
}

collectionView is not showing in UITableViewController

I want to show a UICollectionView in a UITableViewController class. I have seen videos and codes of that working, but apparently it is not working in Swift 5 anymore or at least I don't know how to set it up in Swift 5. I do everything programmatically. This is the function I am calling in my viewDidLoad() but it doesn't seem to be working:
func configureCollectionView() {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height - (tabBarController?.tabBar.frame.height)! - (navigationController?.navigationBar.frame.height)!)
collectionView = UICollectionView(frame: frame, collectionViewLayout: layout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.alwaysBounceVertical = true
collectionView.backgroundColor = .white
collectionView.register(SearchCell.self, forCellWithReuseIdentifier: "SearchCell")
tableView.addSubview(collectionView)
tableView.separatorColor = .clear
}
I am also calling these collectionView functions:
minimumInteritemSpacingForSectionAt
minimumLineSpacingForSectionAt
sizeForItemAt
numberOfItemsInSection
cellForItemAt
didSelectItemAt
What can I do to solve my problem?
set it up like this
collectionView.backgroundColor = .black, can you see the black background?

CollectionView ItemHeight is big than Collectionview Height

Thanks to help.
As shown in the above,CollectionView ItemSize.height is big than CollectionView.height.
And I just set the itemSize in viewDidLayoutSubviews()
override func viewDidLayoutSubviews() {
resizeCollectionView(size: collectionView.frame.size)
}
private func resizeCollectionView(size: CGSize){
print("collectionViewSize:\(size)")
print("viewSize:\(view.frame.size)")
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.itemSize = CGSize(width: size.width, height: collectionView.frame.size.height)
layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
collectionView?.layoutIfNeeded()
print("itemSize:\(layout.itemSize)")
}
}
The print show that CollectionViewSize is equal ItemSize, But the actual, itemSize always big than CollectioinViewSize.
Use this method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: yourWidth, height: yourCollectionView.bounds.height)
}

How to set the collection view cell size exactly equal to the collection view in iOS?

I want to set a collection view where it is only displayed one element at the time and it scrolls horizontally. I want to know how to set the same size for both if the collection view has equal width with the superview (phone size).
Any help will be really appreciated.
Simple answer :
Add UICollectionViewDelegateFlowLayout to your class
and then use this method:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: yourCollectionView.bounds.width, height: yourCollectionView.bounds.height)
}
to make it horizontal:
if you want to add it programmatically you can try this:
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .white
cv.delegate = self
cv.dataSource = self
cv.isPagingEnabled = true
cv.showsHorizontalScrollIndicator = false
return cv
}()
Try this code:
To set collectionView scroll Direction Programmically.
override func viewDidLoad() {
super.viewDidLoad()
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
}
To set collectionView layout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.invalidateLayout()
return CGSize(width: self.view.frame.width, height:(self.view.frame.height) // Set your item size here
}
Note: Layout works tested in Swift 3. But, I want you to consider using page view instead.If you not passing any data from CollectionView.

UICollectionViewController Error in Swift 3.0: must be initialized with a non-nil layout parameter

I'm new to iOS development.
I've been learning Swift, and today, I tried using UICollectionViewController.
My code is as follows:
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var colView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 90, height: 120)
colView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
colView.dataSource = self
colView.delegate = self
colView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
colView.backgroundColor = UIColor.white
self.view.addSubview(colView)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 14
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath)
cell.backgroundColor = UIColor.orange
return cell
}
}
However, when I try to run it, I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'
I have looked up previous posts discussing this issue, but I couldn't find anything that fixed my code.
How should I fix this?
Thank you! I incorporated your suggestions. Below is the code that works:
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let cellId = "CellId"
var colView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 111, height: 111)
colView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
colView.delegate = self
colView.dataSource = self
colView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
colView.backgroundColor = UIColor.white
self.view.addSubview(colView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 21
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath)
cell.backgroundColor = UIColor.orange
return cell
}
}
Again, thank you guys very much. Have an awesome day :D
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let cellSize = CGSize(width: 90, height: 120)
//
return CGSizeMake(cellSize)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(top: 20, left: 10, bottom: 10, right: 10)
}
This should work:
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
return collectionView
}()
Just change the order like below one :
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 90, height: 120)
colView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
self.view.addSubview(colView)
colView.delegate = self
colView.dataSource = self
colView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
colView.backgroundColor = UIColor.white
You can set your code like this:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let cellId = "Cell"
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
// ... layout parameters
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .white
cv.delegate = self
cv.dataSource = self
return cv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(collectionView)
// ... add your auto layout constraints to the collection view
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
}
// Delegate and Data Source Methods...
}

Resources