Stop Single UICollectionView cell Flowing to the centre of the screen

后端 未结 4 1848
名媛妹妹
名媛妹妹 2021-01-11 15:45

I am trying to understand why Collection View keeps centre aligning just the last cell in a collection.
I have created a simple Flow layout based collection view. I am

相关标签:
4条回答
  • 2021-01-11 16:29

    In Swift 5

    Use UICollectionViewFlowLayout to align cell to left like below

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .horizontal
    self.collectionView.collectionViewLayout = layout
    
    0 讨论(0)
  • 2021-01-11 16:31

    When the last cell (only) is showing, try view debugging -> capture view hierarchy (ie. assuming you ran in simulator). My hunch: your cell is growing in size once you have only one left

    0 讨论(0)
  • 2021-01-11 16:34

    If the only requirement difference to a normal UICollectionViewFlowLayout is to ensure that the first item is always left-aligned, it should be enough to simply do just that:

    class MyCustomFlowLayout: UICollectionViewFlowLayout {
    
       override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
            let attributes = super.layoutAttributesForElements(in: rect)
    
            attributes?.first?.frame.origin.x = sectionInset.left
    
            return attributes
        }
    }
    

    The downside of this is that it will only work for the first item of the first section. Alternatively, we can use the index path which conveniently comes with the element attributes:

    class MyCustomFlowLayout: UICollectionViewFlowLayout {
    
       override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
            let attributes = super.layoutAttributesForElements(in: rect)
    
            attributes?.forEach { (elementAttributes) in
                if elementAttributes.indexPath.item == 0 {
                    elementAttributes.frame.origin.x = sectionInset.left
                }
            }
    
            return attributes
        }
    }
    

    It is also possible to target only cells by (in the example above) checking elementAttributes.representedElementCategory, documented here.

    0 讨论(0)
  • 2021-01-11 16:42

    I managed to solve this using the below two steps:

    1. Logged a bug with Apple about the strange behaviour I noticed about the cell behaviour changing when using the UICollectionViewFlowLayoutAutomaticSize
    2. I did a workaround by creating a modified CustomViewFlowLayout ( can't find the original SO/github question where I saw this approach used - I will add it if I find it) I then added the UICollectionViewFlowLayoutAutomaticSize setting - and it's working beautifully.

    Sample code:

    class MyLeftCustomFlowLayout:UICollectionViewFlowLayout {
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    
            let attributes = super.layoutAttributesForElements(in: rect)
    
            var leftMargin = sectionInset.left
            var maxY: CGFloat = 2.0
    
            let horizontalSpacing:CGFloat = 5
    
            attributes?.forEach { layoutAttribute in
                if layoutAttribute.frame.origin.y >= maxY
                    || layoutAttribute.frame.origin.x == sectionInset.left {
                    leftMargin = sectionInset.left
                }
    
                if layoutAttribute.frame.origin.x == sectionInset.left {
                    leftMargin = sectionInset.left
                }
                else {
                    layoutAttribute.frame.origin.x = leftMargin
                }
    
                leftMargin += layoutAttribute.frame.width + horizontalSpacing
                maxY = max(layoutAttribute.frame.maxY, maxY)
            }
    
            return attributes
        }
    

    In the ViewController - you have to add the flow layout to the collection view to make it work:

    let layout = MyLeftCustomFlowLayout() 
    layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
    myCollectionViewReference.collectionViewLayout = layout
    

    I think the implementation for Collection View can definitely be simplified but I am going to look into it more as I can see how powerful it is.

    0 讨论(0)
提交回复
热议问题