I have a problem with a horizontal scroll in collectionView.
I want to scroll by section. I have 3 sections. I want to center it in the view.
First, it looks how I want
But when I scroll next... Left and right insets are different.
The last one is broken too.
I tried it with function scrollViewDidEndDecelerating, but it didn't work. Animation of it was ugly.
My code of collectionView layout.
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
layout.minimumLineSpacing = 5
layout.scrollDirection = .horizontal
You have to implement UICollectionViewDelegateFlowLayout methods to solve this problem.
let minLineSpace = 4
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width - minLineSpace, height: collectionView.frame.size.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return minLineSpace
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, (minLineSpace / 2), 0, (minLineSpace / 2))
}
Here I have added 4 point spacing between two cells, you can customise this as per your requirement.
Related
I have a horizontal collection view that display only 2 images and each image takes up half the screen. I want to prevent scrolling by making images look like they are fixed and no move.
// sizeForItemAt
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if collectionView == self.topCollectionView {
let height = view.frame.size.height
let width = view.frame.size.width
return CGSize(width: width * (1/2), height: height * (1/2))
}
return CGSize()
}
// minimumLineSpacingForSectionAt
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
if collectionView == self.topCollectionView {
return 3
}
return 3
}
// insetForSectionAt
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
if collectionView == self.topCollectionView {
let sectionInset = UIEdgeInsets(top: 3, left: 4, bottom: 3, right: 4)
return sectionInset
}
let sectionInset2 = UIEdgeInsets(top: 3, left: 4, bottom: 3, right: 4)
return sectionInset2
}
I have a UICollectionView that can either have a single cell or two cells.
Is it possible for me to horizontally center the first cell and on panLeft have the second cell centered likewise - to the UICollectionView whose width sizes itself to the screen/view size and cell's proportionally adjusting as well?
From the references I've seen, I believe I need to use the UICollectionViewDelegateFlowLayout insetForSectionAt method, but I'm not able to get it exactly centered for some reason, and also when it is just one cell, I believe the inset causes the UICollectionView to become scrollable because enough space was created..
To make collection view cell center, your controller must confirm UICollectionViewDelegateFlowLayout protocol. Use below code to make cells center:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width * 0.7, height: 300)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
let width = collectionView.frame.width
let margin = width * 0.3
return UIEdgeInsets(top: 10, left: margin / 2, bottom: 10, right: margin / 2)
}
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 collectionView.frame.width * 0.3 / 2
}
If you return 1 or 2 in numberOfItemsInSection method, It works fine.
Im trying to get my collectionView cells to look like the picture bellow but have not been able to do it. I tried using collectionViewLayout but was not able to get the sizing right along with the proper padding. How would I be able to do this?
Here is my code
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
return CGSize(width: frameSize.width, height: frameSize.height / 2)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 27, bottom: 0, right: 27)
}
}
Here is a picture of what I'm trying to achieve. Thanks
Implement the UICollectionViewFlowLayout's following methods
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
and for the 27px inset use
yourcollectionView.sectionInset = UIEdgeInsets(top: 10, left: 27, bottom: 10, right: 27)
To use you class which implements this protocol, you have to set the collection view's delegate property.
yourcollectionView.delegate = /* object which implement flow layout delegate */
UICollctionViewDelegate automatically conform to UICollectionViewFlowLayoutDelegate, setting the delegate is enough.
You are missing another thing while calculating the cell size. Your cell size calculation is wrong. Implement it as follows
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let frameSize = collectionView.frame.size
let size = (frameSize.width - 64.0) / 2.0 // 27 px on both side, and within, there is 10 px gap.
return CGSize(width: size, height: size)
}
If you are using the storyboard to set layout your UI Widget, you can set them in storyboard too.
here is some snap of it i tried with this code but it's not working:
my collecionview cell :
size is : 166 : 32
Min Spacing : 10 : 10
section insets: 20 : 20
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt
indexPath: IndexPath) -> CGSize
{
if collectionView == MainCollectionView
{
let padding : CGFloat = 50
let collectionViewSize = MainCollectionView.frame.size.width - padding
return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}
return CGSize(width: 0, height: 0)
}
Use UICollectionViewDelegateFlowLayout in your view
and call the delegate method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = self.view.frame.width
return CGSize(width: (width)/2, height: (width)/2) // width & height are the same to make a square cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
let width = (collectionView.frame.width/2)-0.5
return CGSize(width:width , height: width)
}
Try implementing these UICollectionViewDelegateFlowLayout delegate methods to achieve the desired result:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
return CGSize(width: (collectionView.bounds.width - 10 - 20*2)/2, height: collectionView.bounds.height)
//In collectionView.bounds.width - 10 - 20*2 :
//10 for cell spacing and
//20*2 for section insets on left and right
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
{
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
return UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
}
Specify your requirements more clearly so that I can help you further.
Your code is perfect but the delegate method you are using is perhaps not getting called. Based on the swift syntax version you are using, try the latest delegate method. And also make sure that you have made your collection view the observer of that delegate by making it self.
collection view had multiple images working fine. it's showing like this
But i want show like this way
this is code of collection view cell
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 10, left: 0, bottom: 20, right: 0)
let width = UIScreen.main.bounds.width
layout.itemSize = CGSize(width: width/2 , height: width/2 )
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout
Just implement some UICollectionViewDelegateFlowLayout methods to get the correct size and spacing of the UICollectionViewCells.
Example:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let cellSize = CGSize(width: (collectionView.bounds.width - (3 * 10))/2, height: 120)
return cellSize
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
{
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
{
let sectionInset = UIEdgeInsetsMake(10, 10, 10, 10)
return sectionInset
}
Just change the size and spacing values according to your requirement.
Add this method on your viewcontroller
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
return CGSize(width: ((self.view.frame.size.width/2) - 10), height: 255)
}
Try,
collectionViewCellImageView.contentMode = .scaleToFill
You can try to set minimum spacing for cell & line for collection view and implement the bellow delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (collectionView.frame.width/2) - 5, height: collectionView.frame.width/2)
}