UICollectionView自上浆细胞自动布局 [英] UICollectionView Self Sizing Cells with Auto Layout

查看:461
本文介绍了UICollectionView自上浆细胞自动布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让自身大小UICollectionViewCells带自动布局的工作,但我似乎无法得到的细胞大小自己的内容。我无法理解如何细胞的尺寸是从该单元格的内容查看里面有什么内容更新。

I'm trying to get self sizing UICollectionViewCells working with Auto Layout, but I can't seem to get the cells to size themselves to the content. I'm having trouble understanding how the cell's size is updated from the contents of what's inside the cell's contentView.

下面是我试过的设置:


  • 自定义UICollectionViewCell在其内容查看一个UITextView。

  • 滚动的UITextView的是禁用的。

  • 的内容查看的水平约束条件是:H:| [_textView(320)]。即UITextView的被固定在细胞的左侧为320的显式宽度

  • 的内容查看的垂直约束是:V:| -0 - [_的TextView],即UITextView的固定到电池的顶部

  • 的UITextView的具有高度约束设置为常数的UITextView的报告将适合文本。

下面是它看起来像单元格的背景设置为红色,背景UITextView的设置为蓝色:

Here's what it looks like with the cell background set to red, and the UITextView background set to Blue:

我把,我一直在GitHub上玩这里项目。

I put the project that I've been playing with on GitHub here.

推荐答案

的iOS 9下看到我的GitHub的解决方案的休息之后,我终于得到了全面调查该问题的时间。现在我已经更新了回购协议,包括自细胞大小不同配置的几个例子。我的结论是,自上浆细胞是在理论上很好,但在实践中凌乱。自细胞大小时,继续小心的话。

Updated for iOS 9

After seeing my GitHub solution break under iOS 9 I finally got the time to investigate the issue fully. I have now updated the repo to include several examples of different configurations for self sizing cells. My conclusion is that self sizing cells are great in theory but messy in practice. A word of caution when proceeding with self sizing cells.

TL; DR

看看我的的GitHub项目

自上浆细胞仅与流布局支持,以便让你使用的是什么肯定多数民众赞成。

Self sizing cells are only supported with flow layout so make sure thats what you are using.

有你需要设置自上浆细胞工作的两件事情。

There are two things you need to setup for self sizing cells to work.

流布局将成为动态性。

Flow layout will become dynamic in nature once you set the estimatedItemSize property.

self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)

2。添加在你的细胞亚类上浆支持

这也有两个口味;自动布局的自定义覆盖 preferredLayoutAttributesFittingAttributes

我不会去的细节,关于这个问题,有一个辉煌的<一个href=\"http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights\">SO帖子有关配置约束的单元格。只是要警惕<一个href=\"http://stackoverflow.com/questions/25804588/auto-layout-in-uicollectionviewcell-not-working?rq=1\">X$c$c 6打破一堆东西与iOS 7的话,如果你支持的iOS 7,你需要做的东西一样确保autoresizingMask是该单元格的内容查看,而且内容查看的边界设置设置为单元的边界时,细胞被加载(即 awakeFromNib )。

I won't go to in to detail about this as there's a brilliant SO post about configuring constraints for a cell. Just be wary that Xcode 6 broke a bunch of stuff with iOS 7 so, if you support iOS 7, you will need to do stuff like ensure the autoresizingMask is set on the cell's contentView and that the contentView's bounds is set as the cell's bounds when the cell is loaded (i.e. awakeFromNib).

你需要知道的事情是,你的电池需要比表格视图单元格更加严重制约。举例来说,如果你希望你的宽度是动态的那么你的电池需要一个高度约束。同样的,如果你要的高度是动态的,那么你将需要一个宽度约束到您的。

Things you do need to be aware of is that your cell needs to be more seriously constrained than a Table View Cell. For instance, if you want your width to be dynamic then your cell needs a height constraint. Likewise, if you want the height to be dynamic then you will need a width constraint to your cell.

当这个函数被调用你的观点已经配置与内容(即 cellForItem 被调用)。假设你的约束已正确设定,你可以有一个这样的实现:

When this function is called your view has already been configured with content (i.e. cellForItem has been called). Assuming your constraints have been appropriately set you could have an implementation like this:

//forces the system to do one layout pass
var isHeightCalculated: Bool = false

override func preferredLayoutAttributesFittingAttributes(layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
    //Exhibit A - We need to cache our calculation to prevent a crash.
    if !isHeightCalculated {
        setNeedsLayout()
        layoutIfNeeded()
        let size = contentView.systemLayoutSizeFittingSize(layoutAttributes.size)
        var newFrame = layoutAttributes.frame
        newFrame.size.width = CGFloat(ceilf(Float(size.width)))
        layoutAttributes.frame = newFrame
        isHeightCalculated = true
    }
    return layoutAttributes
}

注意在iOS版9的行为改变了一点,可能会导致您的实现崩溃,如果你不小心(查看更多的这里)。当你实施 preferredLayoutAttributesFittingAttributes 你需要确保你只能改变你的布局的框架属性一次。如果你不这样做的布局将无限期地打电话给你的实现,并最终崩溃。一种解决方案是缓存大小计算在你的细胞,这任何时候你重新使用无效的单元格或更改其内容,我与 isHeightCalculated 属性来实现。

NOTE On iOS 9 the behaviour changed a bit that could cause crashes on your implementation if you are not careful (See more here). When you implement preferredLayoutAttributesFittingAttributes you need to ensure that you only change the frame of your layout attributes once. If you don't do this the layout will call your implementation indefinitely and eventually crash. One solution is to cache the calculated size in your cell and invalidate this anytime you reuse the cell or change its content as I have done with the isHeightCalculated property.

在这一点上,你应该有'功能'在你的CollectionView动态细胞。我还没有发现在我的测试中出的最现成的解决方案足以使随时,如果你有意见。它仍然感觉像的UITableView 赢得了动态调整大小恕我直言战斗。

At this point you should have 'functioning' dynamic cells in your collectionView. I haven't yet found the out-of-the box solution sufficient during my tests so feel free to comment if you have. It still feels like UITableView wins the battle for dynamic sizing IMHO.

非常小心,如果你正在使用的原型细胞计算estimatedItemSize - 这将打破,如果你的<一个href=\"http://stackoverflow.com/questions/27735341/offscreen-uitableviewcells-for-size-calculations-not-respecting-size-class\">XIB使用大小类。这样做的原因是,当你从厦门国际银行加载电池的规模类将与未定义进行配置。这将只在iOS 8被打破,最多,因为在iOS 7的尺寸级别将根据设备上加载(新iPad =普通任意,iPhone =紧凑型任意)。您可以设置estimatedItemSize而不载入厦门国际银行,也可以从XIB装入电池,将其添加到的CollectionView(这将设置traitCollection),进行布局,然后从上海华删除它。或者你也可以让你的细胞覆盖 traitCollection getter和返回相应的特征。随你便。

Be very mindful that if you are using prototype cells to calculate the estimatedItemSize - this will break if your XIB uses size classes. The reason for this is that when you load your cell from a XIB its size class will be configured with Undefined. This will only be broken on iOS 8 and up since on iOS 7 the size class will be loaded based on the device (iPad = Regular-Any, iPhone = Compact-Any). You can either set the estimatedItemSize without loading the XIB, or you can load the cell from the XIB, add it to the collectionView (this will set the traitCollection), perform the layout, and then remove it from the superview. Alternatively you could also make your cell override the traitCollection getter and return the appropriate traits. It's up to you.

让我知道如果我错过了什么,希望我帮助,祝你好运编码

Let me know if I missed anything, hope I helped and good luck coding

这篇关于UICollectionView自上浆细胞自动布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆