UICollectionViewFlowLayout:collectionView!.contentSize vs collectionViewContentSize

时间:2015-04-28 10:25:46

标签: ios swift uicollectionview uicollectionviewlayout uikit-dynamics

更新

使用指定的collectionViewContentSize()方法时似乎解决了这个问题:

let contentSize = collectionViewContentSize()

尽管如此,我对此行为背后的解释非常感兴趣,所以我已相应地更新了我的问题。

原始问题

我正在尝试重新创建this article的第一个示例中的步骤,但是使用Swift和Storyboards。

我有一个自定义UICollectionViewFlowLayout子类,其中包含以下内容: 导入UIKit

class SpringyFlowLayout: UICollectionViewFlowLayout {

    private lazy var animator: UIDynamicAnimator = {
        return UIDynamicAnimator(collectionViewLayout: self)
        }()

    override func prepareLayout() {
        super.prepareLayout()

        let contentSize = collectionView!.contentSize
        let items = super.layoutAttributesForElementsInRect(CGRect(origin: CGPointZero, size: contentSize)) as! [UICollectionViewLayoutAttributes]

        if animator.behaviors.isEmpty {
            for item in items {
                let spring = UIAttachmentBehavior(item: item, attachedToAnchor: item.center)
                spring.length = 0
                spring.damping = 0.8
                spring.frequency = 1.0
                animator.addBehavior(spring)
            }
        }
    }

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
        return animator.itemsInRect(rect)
    }


    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
        return animator.layoutAttributesForCellAtIndexPath(indexPath)
    }

    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
        let delta = newBounds.origin.y - collectionView!.bounds.origin.y
        for spring in animator.behaviors {
            let items = spring.items as! [UICollectionViewLayoutAttributes]
            if let attributes = items.first {
                attributes.center.y += delta
                animator.updateItemUsingCurrentState(attributes)
            }
        }
        return false
    }

我在Storyboards中设置了正确的Layout类。当我运行应用程序时,我的集合视图为空。

我已确定问题出现在以下内容中:

override func prepareLayout() {
        super.prepareLayout()

        let contentSize = collectionView!.contentSize
        let items = super.layoutAttributesForElementsInRect(CGRect(origin: CGPointZero, size: contentSize)) as! [UICollectionViewLayoutAttributes]
//...
}

由于我是UICollectionViewFlowLayout的子类,我认为我可以依靠超级实现来为我布置元素,然后修改它们的属性。但是当我检查contentSize时,它会正确报告宽度,但高度为0.

这导致空项目数组 - > animator中没有行为 - > animator.itemsInRect(_)返回一个空数组 - >空的集合视图。

我似乎无法找出我所缺少的东西。应该不需要覆盖contentSize()方法,因为我正在使用流布局。

2 个答案:

答案 0 :(得分:3)

collectionView还没有内容大小的问题,因为它刚刚开始准备它的布局。我不相信调用import agrparse ... parser.add_argument("-m", "--mode", nargs="*", default=["fizz", "bazz", "razmataz"], help="Comma separated list of mode(s) to use, e.g." "[\"fizz\", \"bazz\"]") main(parser.parse_args()) 实际上会计算大小。 collectionView!.contentSize工作的原因是因为它会使用您的其他布局代码计算大小。

答案 1 :(得分:1)

这里有一些你可能感兴趣的东西。我在Ash Furrow的example中注意到viewDidAppear对collectionViewLayout.invalidateLayout的调用。 Ash指出,在使用故事板时,由于第一次调用prepareLayout与不使用故事板时的时间不同,因此这是不必要的。

我尝试在viewDidAppear中使用您的代码和故事板使集合视图布局无效。这是我发现的:

测试场景:

1)collectionView!.contentSize没有invalidateLayout = cv是EMPTY

2)collectionViewContentSize()没有invalidateLayout = cv WORKS

3)collectionView!.contentSize with invalidateLayout = cv WORKS

4)collectionViewContentSize()with invalidateLayout = cv WORKS

FYI