在UICollectionViewLayout(支持iOS 9)中自动调整单元格而不使用“invalidateLayout”跳转

时间:2017-07-11 10:16:45

标签: ios uicollectionview uicollectionviewlayout

我一直在阅读this article about using custom UICollectionViewLayouts并试图将这个想法纳入我正在进行的项目中。

我们以前使用一个具有巨大丑陋功能的UICollectionViewFlowLayout子类来确定单元格的大小,方法是将原型单元格出列并填充,然后询问它的大小。

毋庸置疑,我想找到一种更好的方法。

我遇到的问题是细胞的初始布局。我们使用的很多单元格包含1或2个标签,这些标签可能包含大量文本并需要换行。在链接的文章中有一个操场,显示自动调整大小的多行标签,但它会在文本中插入换行符以强制显示...

在Datasource.swift文件中......

lazy private var values: [String] = {
    return (0...255).map {
        _ in
        switch arc4random_uniform(3) {
        case 0: return "Hello"
        case 1: return "Hello\nGoodbye"
        default: return "Hello\nGoodbye\nAu revoir"
        }
    }
}()

但是,如果我将这些更改为不同长度的字符串会自然地破坏它会打破这个例子。初始布局只在标签中有一行。但是,滚动标签会正确显示。

我可以"修复"这可以通过在layout.invalidateLayout()文件中添加行Autosizing

现在,我在自己的项目中尝试做同样的事情。如果我将layout.invalidateLayout()函数放在viewDidAppear函数中,则invalidateLayout仅适用于视图控制器。这意味着我们在转换布局不正确之后得到一个尴尬的跳跃,然后跳转"到正确的布局。但是,我觉得使用intelligently的整个方法都被打破了。

有没有办法可以让它不破坏初始布局?或者override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // This invalidation "fixes" the layout but causes a jump in the UI collectionView?.collectionViewLayout.invalidateLayout() } 使单元格初始布局无效?

我添加了GitHub project,显示了我遇到的问题。目前由于代码正确布局......

var customer = new Schema({
  cash: {
    type: Number,
    minimum: 0
  }
});

理想情况下,我想删除此功能并进行布局"只需工作"。

1 个答案:

答案 0 :(得分:2)

这里的问题是,在初始传递时,单元格返回的首选布局属性不正确 - 它根据看似无限的宽度调整标签大小,因此您最终希望适合一行。

将此行添加到单元格setUp()方法“修复”问题:

label.preferredMaxLayoutWidth = self.bounds.width - (contentView.layoutMargins.left + contentView.layoutMargins.right)

有点脏,我确信有更好的方法。

修改

好的,这是一个更好的方法。这会强制您的视图进入布局中的原始估计帧,从而使AL引擎有机会正确调整单元格的大小。在您的单元子类中执行此操作:

private var isInitialLayout = true

public override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    if isInitialLayout {
        self.contentView.layoutIfNeeded()
        isInitialLayout = false
    }
    return super.preferredLayoutAttributesFitting(layoutAttributes)
}