I have 10 cells out of which the width of the 6th cell has to be different from others.I tried to change it in the flow delegate method. but something is going wrong with the spacing from 7th to 10th cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let widthOfCollectionView = collectionView.bounds.width - 40;
// For collectionView use "item" instead of "row"
if indexPath.item == 6{
return CGSizeMake(widthOfCollectionView,100)
}else{
return CGSizeMake(widthOfCollectionView/3, 100)
}
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 10;
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 10;
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets{
return UIEdgeInsetsMake(5, 5, 5, 5);
}
I made some changes to your code as follows:
import UIKit
class ViewController: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var sampleCollectionView: UICollectionView!
let reuseIdentifier = "cell"
let insetValue: CGFloat = 5.0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
// make a cell for each cell index path
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
// Use the outlet in our custom class to get a reference to the UILabel in the cell
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if indexPath.item == 6{
return CGSizeMake(collectionView.bounds.width - insetValue * 2,100)
}else{
return CGSizeMake(floor((collectionView.bounds.width - insetValue * 4)/3), 100)
}
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return insetValue;
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return insetValue;
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets{
return UIEdgeInsetsMake(insetValue, insetValue, insetValue, insetValue);
}
}
Final output:
To download the sample project, use the following link:
https://github.com/k-sathireddy/SampleCollectionView
For the width of small items you should return (collectionView.bounds.width - 30)/3, 5 for left inset, 5 for right inset and 2*10 for spacing = 30.
For the width of large item you should return collectionView.bounds.width - 10, 5 for left and 5 for right inset = 10.
You can replace this
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let widthOfCollectionView = collectionView.bounds.width - 40;
if indexPath.item == 6{
return CGSizeMake(widthOfCollectionView,100)
}else{
return CGSizeMake(widthOfCollectionView/3, 100)
}
}
With
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let smallItemWidth = floor((collectionView.bounds.width - 30)/3 * 1000) / 1000
let largeItemWidth = collectionView.bounds.width - 10
if indexPath.item == 6{
return CGSizeMake(largeItemWidth, 100)
}else{
return CGSizeMake(smallItemWidth, 100)
}
}
*Use floor() to round down large decimals
Related
I am getting the space between the cells (marked with blue color):
extension ProfileVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if collectionView == self.humanCollectionView {
let screenWidth = humanCollectionView.bounds.width
return CGSize(width: screenWidth/3-0, height: screenWidth/3-0)
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, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
Why are you declaring the delegate functions inside collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) delegate method?
Try to do like this:
import UIKit
class ProfileVC: UICollectionViewController {
override func viewDidLoad() {
super.viewDidLoad()
//remember to set the delegates
self.collectionView.delegate = self
self.collectionView.dataSource = self
//this is optional just to test that it is working
collectionView.backgroundColor = .red
// Do any additional setup after loading the view.
}
}
extension ProfileVC: UICollectionViewDelegateFlowLayout {
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//this is just a test number, here you should return the number of your items
return 20
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//you should set reuseIndetifier in storyboard or in code if you create your collectionView programmatically
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "reuseIdentifier", for: indexPath)
//again this is just a placeholder color to see that it's working
cell.backgroundColor = .green
return cell
}
func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize {
let screenWidth = collectionView.bounds.width
//be sure to use floor or to use a number of items that perfectly fits the width of collectionView
return CGSize(width: floor(screenWidth/3), height: floor(screenWidth/3))
}
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, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
I want to add that if the width of your collectionView is not perfectly divisible by 3, you will always have some gap between the cells. You should do the math by yourself for each device width and choose a proper number of cells for the width. For example for a screen with aspect ratio like iPhone X, I would use 3 cells when in portrait and 4 cells when in landscape.
You can do like this:
func collectionView(_ collectionView: UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize {
let screenWidth = collectionView.bounds.width
let screenHeight = collectionView.bounds.height
let numberOfCells : CGFloat = screenWidth > screenHeight ? 4 : 3
return CGSize(width: floor(screenWidth/numberOfCells), height: floor(screenWidth/numberOfCells))
}
In my uicollectionview cells are loaded in sections. but the number of sections in the collectionview is 1. when sections are breaking there is a space between cells which i need to avoid.
func cellSize() -> CGSize {
let collectionViewSize: CGSize = self.colorScrollCollectionView.frame.size
return CGSize(width: collectionViewSize.width, height: collectionViewSize.width * 0.35)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.colorArray.count * 5
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSize = CGSize(width: self.cellSize().width, height: self.cellSize().height)
return cellSize
}
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 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.
I'm trying to create a CollectionView with cells. However, it seems to keep hiding the top of the first cells. Of course, I can set the top insets, however, isn't there another way to do it, or what am I doing wrong?
I've created a UICollectionViewController and set the following.
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFCollectionViewCell? {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ItemCell", forIndexPath: indexPath) as? BrowseCell
cell?.titleLabel.text = object["title"] as! NSString as String
// cell?.myImageView.file = (object["images"] as [PFFile]).first
cell?.clipsToBounds = true
return cell
}
override func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 10
}
override func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(0, 10, 0, 10)
}
override func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(self.view.frame.width/2-15, 100)
}
an image