可变宽度和宽度使用带故事板的AutoLayout(不带XIB)的UICollectionViewCell的高度 [英] Variable width & height of UICollectionViewCell using AutoLayout with Storyboard (without XIB)

查看:110
本文介绍了可变宽度和宽度使用带故事板的AutoLayout(不带XIB)的UICollectionViewCell的高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是应用程序中的一个设计问题,它使用AutoLayout,UICollectionView和UICollectionViewCell,它可以自动调整宽度和宽度。高度取决于AutoLayout约束及其内容(某些文本)。

Here is an design issue in the app that uses AutoLayout, UICollectionView and UICollectionViewCell that has automatically resizable width & height depending on AutoLayout constraints and its content (some text).

这是一个UITableView列表,每个单元格都有自己的宽度和宽度。高度根据其内容为每一行单独计算。它更像是在应用程序(或WhatsUp)中构建的iOS消息。

It is a UITableView list like, with each cell that has it's own width & height calculated separately for each row dependant on its content. It is more like iOS Messages build in app (or WhatsUp).

显然应用程序应该使用 func collectionView(collectionView:UICollectionView) ,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) - > CGSize

It is obvious that app should make use of func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize.

问题是在该方法中,app无法调用 func collectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath: NSIndexPath) - > UICollectionViewCell 也不是 dequeueReusableCellWithReuseIdentifier(标识符:String,forIndexPath indexPath:NSIndexPath!) - > AnyObject 实例化单元格,用特定内容填充它并计算其宽度和宽度。高度。尝试这样做会导致无限期递归调用或其他类型的应用程序崩溃(至少在iOS 8.3中)。

Issue is that within that method, app cannot call func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell nor dequeueReusableCellWithReuseIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath!) -> AnyObject to instantiate cell, populate it with specific content and calculate its width & height. Trying to do that will result in an indefinite recursion calls or some other type of app crash (at least in iOS 8.3).

最接近解决这种情况的方法似乎是将单元格的定义复制到视图层次结构中以允许自动布局自动调整单元格大小(就像单元格具有与父集合视图相同的宽度),因此应用程序可以配置具有特定内容的单元格并计算其大小。由于资源重复,这绝对不是修复它的唯一方法。

The closest way to fix this situation seems to copy definition of the cell into view hierarchy to let Auto-layout resize "cell" automatically (like cell to have the same width as parent collection view), so app can configure cell with specific content and calculate its size. This should definitely not be the only way to fix it because of duplicated resources.

所有这一切都与将UILabel.preferredMaxLayoutWidth设置为应该是Auto-Layout的某个值有关。可控制的(不是硬编码的)可能取决于屏幕宽度&高度或至少通过自动布局约束定义设置,因此应用程序可以获得多行UILabel内在大小计算。

All of that is connected with setting UILabel.preferredMaxLayoutWidth to some value that should be Auto-Layout controllable (not hardcoded) that could depend on screen width & height or at least setup by Auto-layout constraint definition, so app can get multiline UILabel intrinsic size calculated.

我不想实例化XIB文件中的单元格,因为Storyboard应该是今天的行业标准,我希望减少对代码的干预。

I would not like to instantiate cells from XIB file since Storyboards should be today's industry standard and I would like to have as less intervention in code.

编辑:

基本下面列出了无法运行的代码。因此,仅实例化变量cellProbe(未使用)会使应用程序崩溃。没有那个电话,应用程序运行顺畅。

The basic code that cannot be run is listed bellow. So only instantiating variable cellProbe (not used) crashes the app. Without that call, app runs smoothly.

var onceToken: dispatch_once_t = 0

class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

        dispatch_once(&onceToken) {

            let cellProbe = collectionView.dequeueReusableCellWithReuseIdentifier("first", forIndexPath: NSIndexPath(forRow: 0, inSection: 0)) as! UICollectionViewCell
        }

        return CGSize(width: 200,height: 50)
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("first", forIndexPath: NSIndexPath(forRow: 0, inSection: 0)) as! UICollectionViewCell

        return cell
    }
}


推荐答案

如果使用约束,则无需为每个单元格设置大小。所以你应该删除你的委托方法 func collectionView(collectionView:UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) - > CGSize

If you are using constraints, you don't need to set a size per cell. So you should remove your delegate method func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize

相反,你需要在 estimatedItemSize 中设置一个大小,方法是将其设置为除了 CGSizeZero 以外的值,您告诉布局您还不知道确切的大小。然后布局将询问每个单元格的大小,并在需要时进行计算。

Instead you need to set a size in estimatedItemSize by setting this to a value other than CGSizeZero you are telling the layout that you don't know the exact size yet. The layout will then ask each cell for it's size and it should be calculated when it's required.

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.estimatedItemSize = someReasonableEstimatedSize()

这篇关于可变宽度和宽度使用带故事板的AutoLayout(不带XIB)的UICollectionViewCell的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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