停止单个UICollectionView单元格流向屏幕中心

时间:2017-04-06 22:44:17

标签: ios uicollectionview uicollectionviewlayout

我试图理解为什么Collection View保持居中对齐集合中的最后一个单元格  我创建了一个简单的基于Flow布局的集合视图。我正在使用Autolayout标志 - 我不确定是否会导致此问题。

每当我从Collection视图中删除一个单元格时 - 前几个似乎工作正常并向左滚动。然而,当我移除倒数第二个时,突然最后一个单元从左对齐变为中心对齐。 有人有解释吗?这看起来很奇怪。

如何制作它以使所有单元格向左滚动并保持与左对齐。

编辑:这是视图层次调试: http://imgur.com/a/NxidO

以下是行为

Collectionview centring

我制作了一个简单的github来演示它:https://github.com/grantkemp/CollectionViewIssue

这是代码:

        var dataforCV = ["short","longer phrase", "Super long Phrase"]

override func viewDidLoad() {
        super.viewDidLoad()
        demoCollectionView.reloadData()
    let layout = UICollectionViewFlowLayout()

    // Bug Description  - > UICollectionViewFlowLayoutAutomaticSize will center Align the layout if it has only a single cell - but it will left align the content if there is more than one cell.

    // I would expect this behaviour to be consistently left aligning the content.

    //How to repeat: If you comment out UICollection​View​Flow​Layout​Automatic​Size then the collection view will show 3 cells being left aligned and it will continue to left align all the content no matter how many cells you remove.

    // But: if you leave turn UICollection​View​Flow​Layout​Automatic​Size on - then it will intially show 3 cells being left aligned, and then as you click to remove each cell they will stay left aligned until the last single cell will suddenly center align in the collection view

    //  see here for the screen recording:https://i.stack.imgur.com/bledY.gif
    //  see here for the view hierachy debuggins screen: http://imgur.com/a/NxidO

    layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize


    // <-- End Bug Description
    demoCollectionView.collectionViewLayout = layout
}

    //MARk: CollectionView

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? collectionCell
        cell?.text.text  = dataforCV[indexPath.row]

        return cell!

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataforCV.count
    }
    //Remove the item from the array if selected
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        dataforCV.remove(at: indexPath.row)
        demoCollectionView.deleteItems(at: [indexPath])
    }

5 个答案:

答案 0 :(得分:7)

我设法使用以下两个步骤解决了这个问题: 1.记录了一个关于使用UICollectionViewFlowLayoutAutomaticSize时我注意到有关细胞行为变化的奇怪行为的Apple的错误 2.我通过创建一个修改过的CustomViewFlowLayout做了一个工作(找不到原始的SO / github问题,我看到这个方法使用了 - 如果我找到的话我会添加它)然后我添加了UICollectionViewFlowLayoutAutomaticSize设置 - 并且它工作得很漂亮。

示例代码:

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
    }

在ViewController中 - 您必须将流程布局添加到集合视图中才能使其工作:

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

我认为Collection View的实现绝对可以简化,但我会更多地研究它,因为我可以看到它有多强大。

答案 1 :(得分:5)

在Swift 5中

使用UICollectionViewFlowLayout将单元格向左对齐,如下所示

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.collectionView.collectionViewLayout = layout

答案 2 :(得分:0)

当显示最后一个单元格(仅)时,请尝试查看调试 - &gt; 捕获视图层次结构(即假设您在模拟器中运行)。我的预感:一旦你只有一个

,你的细胞就会变大

答案 3 :(得分:0)

如果与普通UICollectionViewFlowLayout的唯一要求差异是确保第一项始终保持左对齐,则只需执行以下操作就足够了:

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
    }
}

其缺点是它仅适用于第一部分的第一项。另外,我们可以使用元素属性附带的索引路径:

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
    }
}

通过(在上面的示例中)检查here中记录的elementAttributes.representedElementCategory,也可以仅定位单元格。

答案 4 :(得分:0)

这是我从 here 那里得到的。它对我有用,将估计大小设置为无

enter image description here