How do I set collection view's cell size via the auto layout
Asked Answered
S

5

19

Hi I'm trying to resize the cell via the auto layout.

I want display the cell by the 3 by 3.

First Cell's margin left=0

Last Cell's margin right=0

And all of the cell's space has 1pt. Like an instagram.

enter image description here

enter image description here

Should I set to Cell's Size? I want set constraint via the Autolayout.

I also trying to set cell's size using the code.

Here is my code:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSizeMake(123, 123);
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
    return 1;
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
    return 1;
}

But..I think it is not exactly calculate the cell's size.

How do I set cell's size depending on the screen's size?

I have to set space the 1pt between cell's.

Is there anyway to set only using the storyboard?

If not, How do I set by the code?

Thank you.

Sining answered 25/6, 2016 at 4:56 Comment(0)
M
29

I don't believe you can set the size by only using the Storyboard because you can't set constraints to recurring items like collection view cells that are created on the fly at runtime.

You can easily compute the size from the information you are given. In collectionView(_:layout:sizeForItemAt:) you can access the bounds of the collectionView to compute the desired size of your cell:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    // Compute the dimension of a cell for an NxN layout with space S between
    // cells.  Take the collection view's width, subtract (N-1)*S points for
    // the spaces between the cells, and then divide by N to find the final
    // dimension for the cell's width and height.

    let cellsAcross: CGFloat = 3
    let spaceBetweenCells: CGFloat = 1
    let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
    return CGSize(width: dim, height: dim)
}

Make sure your class adopts the protocol UICollectionViewDelegateFlowLayout.

This then works for iPhones and iPads of all sizes.

Minorca answered 25/6, 2016 at 12:18 Comment(10)
Don't collection view cells support automatic sizing now?Prevenient
I don't know @ThuggishNuggets. You'd have to somehow provide the same kind of information that I'm handling here such as number of cells across and desired spacing between the cells. If you know of another or better way to do it, please add an answer.Minorca
Thanks you so much~!Sining
Thanks you so much~! I've test your code on iPhone6. It really helpful! :) I have a one more question. It seems all of the cell's width is 124. And It has a gap 1pt. First Cell and Second Cell is looks great but Second and Last Cell's gap is small. I think it is happened because of the float values like an 124.3333.Sining
I would just make the gap a little larger to make the difference less noticeable.Minorca
@Minorca I understand thanks for the helping me. I'm really appreciate for you :)Sining
Worked return CGSize(width: ((collectionView.frame.size.width/2)-2) , height: (collectionView.frame.size.width/2)-2) in my caseLimitary
And don't forget to set Estimate Size to None on Size Inspector if you are using this method. Unless it won't work..Kalina
Please do I need to implement something before I can access sizeForItemAt ? Because I cant find itWo
@DanielKabuAsare, make sure your class adopts UICollectionViewDelegateFlowLayout.Minorca
D
16

Great answer by vacawama but I had 2 issues. I wanted the spacing that I defined in storyboard to automatically be used.

enter image description here

And secondly, I could not get this function to invoke and no one mentioned how? In order to invoke the collectionView's sizeForItemAt you need to extend UICollectionViewDelegateFlowLayout instead of extending UICollectionViewDelegate. I hope this saves someone else some time.

extension MyViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let cellsAcross: CGFloat = 3
        var widthRemainingForCellContent = collectionView.bounds.width
        if let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout {
            let borderSize: CGFloat = flowLayout.sectionInset.left + flowLayout.sectionInset.right
            widthRemainingForCellContent -= borderSize + ((cellsAcross - 1) * flowLayout.minimumInteritemSpacing)
        }
        let cellWidth = widthRemainingForCellContent / cellsAcross
        return CGSize(width: cellWidth, height: cellWidth)
    }

}
Diphase answered 25/4, 2017 at 17:32 Comment(0)
C
7

I set it up using CollectionView's delegate methods. This will give you a 2xN setup but you can easily make it a 3xN instead. Here's a screenshot and you can refer to my project on GitHub...

https://github.com/WadeSellers/GoInstaPro

CollectionView flow layout screenshot

Complected answered 25/6, 2016 at 17:7 Comment(0)
M
4

Swift 3 version code based on vacawama answer:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

        let cellsAcross: CGFloat = 3
        let spaceBetweenCells: CGFloat = 1
        let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross

        return CGSize(width: dim, height: dim)
    }
Mcelroy answered 19/4, 2017 at 12:4 Comment(0)
S
0

Here is another solution but It only works on iPhone6.

I will trying to update for iphone5/6plus

Special thanks to @vacawama!

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        
        
        // Compute the dimension of a cell for an NxN layout with space S between
        // cells.  Take the collection view's width, subtract (N-1)*S points for
        // the spaces between the cells, and then divide by N to find the final
        // dimension for the cell's width and height.
        
        let cellsAcross: CGFloat = 3
        let spaceBetweenCells: CGFloat = 1
        let dim = (collectionView.bounds.width - (cellsAcross - 1) * spaceBetweenCells) / cellsAcross
                print(indexPath.row)
        
        var width = dim
        
        //last cell's width
        if(  (indexPath.row + 1) % 3 == 0){
            width = 124
            
        }else {
            width = 124.5
        }
        print(width)
        return CGSize(width: width , height: dim)
        
    }
    
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 1;
    }
    
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 1;
    }
Sining answered 25/6, 2016 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.