使用自动布局约束动态尺寸表视图细胞 [英] Dynamically size Table View Cells using Auto Layout constraints

查看:226
本文介绍了使用自动布局约束动态尺寸表视图细胞的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经完全后,我的最新调查结果修订的问题。

I have revised the question completely after my latest findings.

我的目标是实现以下效果:

My goal is to implement the following effect:


  1. 有一个简单的表格视图

  2. 的用户选择行

  3. 选定行展开,露出下面的原始另一个标签

请注意,我知道,这可以通过插入/删除选择以下任一单元格来实现,我已经有成功实施使用该方法

Please note that I am aware, that this can be achieved by inserting/deleting cells below the selected one, I already have a successful implementation using that method.

这一次,我要尝试实现这一目标使用自动布局约束。

This time, I want to try to achieve this using Auto Layout constraints.

我有一个可用的示例项目的人来检查,也的opened问题。总之,这里是我到目前为止已经试过:

I have a sample project available for anyone to check, and also opened an issue. To summarize, here's what I've tried so far:

我有以下几点看法如下行为:

I have the following views as actors here:


  • 单元格的内容视图

  • 顶视图,包含主标签(主视图)

  • 仰视图,主视图下方,包含最初是隐藏标签(详细信息视图)

我已经设置了自动布局限制我的牢房内的下列方式(请注意,这是严格伪语言):

I have set up Auto Layout constraints within my cell the following way (please note that this is strictly pseudo-language):


  • mainView.top = contentView.top

  • mainView.leading = contentView.leading

  • mainView.trailing = contentView.trailing

  • mainView.bottom = detailView.top

  • detailView.leading = contentView.leading

  • detailView.trailing = contentView.trailing

  • detailView.bottom = contentView.bottom

  • detailView.height = 0

我有一个自定义的的UITableViewCell 子类中,有多个网点,但在这里最重要的是对高度约束的插座提到previously:这里的想法是设置其 0默认,但被选中单元格时,将其设置为44,那么它将变得可见:

I have a custom UITableViewCell subclass, with multiple outlets, but the most important here is an outlet for the height constraint mentioned previously: the idea here is to set its constant to 0 by default, but when the cell is selected, set it to 44, so it becomes visible:

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
    detailViewHeightConstraint.constant = selected ? detailViewDefaultHeight : 0
    UIView.animateWithDuration(0.3) {
        self.layoutIfNeeded()
    }
}

我有以下结果:

所以效果是工作,但不正是我最初的想象。相反,主推的观点了,我想细胞的高度为增长时,将显示详细视图,和缩了回来时,它的隐藏。

So the effect is working, but not exactly how I originally imagined. Instead of pushing the main view up, I want the cell's height to grow when the detail view is shown, and shrink back when it's hidden.

我已经在运行时检查我的布局层次:

I have examined my layout hierarchy during runtime:


  • 的初始状态是确定。内容视图的高度等于我主视图的高度(在此情况下,它的125点)。


  • 当选择小区,则细节视图的高度约束增加至44点和两个视图被正确层叠vertically.But代替单元格的内容视图延伸,而是,主视图收缩。

我需要的是以下几点:表格视图单元格的内容视图的高度应等于

What I need is the following: the height of table view cell's content view should be equal to


  • 主视图的高度,当详细视图的身高限制是0(目前这个工程)

  • 主视图高度+时,详细视图的高度约束已正确设置详细视图高度(这不起作用)。

我如何必须设置我的约束来实现这一目标?

How do I have to set my constraints to achieve that?

推荐答案

研究的显著量之后,我想我已经发现的这篇大文章。

After a significant amount of research, I think I've found the solution with the help of this great article.

下面是使细胞大小调整所需的步骤:

Here are the steps needed to make the cell resize:

在Main和详细视图,我原本设定为水平,垂直居中的标​​签。这是不够的,自我上浆细胞。我需要的第一件事是使用垂直间隔的限制,而不是简单的校准设置我的布局:

Within the Main, and Detail Views, I have originally set the labels to be horizontally and vertically centered. This isn't enough for self sizing cells. The first thing I needed is to set up my layout using vertical spacing constraints instead of simple alignment:

此外,你应该设置在主箱的垂直COM pression阻力为1000。

Additionally you should set the Main Container's vertical compression resistance to 1000.

详细视图更是一个有点棘手:除了建立适当的垂直约束,你也有自己的优先级发挥,达到预期的效果:

The detail view is a bit more tricky: Apart from creating the appropriate vertical constraints, you also have to play with their priorities to reach the desired effect:


  • 的明细集装箱的高度约束为44分,而是使之选,(根据文档,任何比要求,下将被视为这样的),设置其优先级为999。

  • 在明细集装箱,建立垂直间隔的限制,并给他们的998当务之急。

主要思路如下:


  • 默认情况下,该电池已展开。为了实现这一目标,我们必须编程设置明细集装箱的高度约束的常数0。由于其优先级高于单元格内容视图中的垂直限制较高,后者将被忽略,所以明细集装箱将被隐藏。

  • 当我们选择单元格,我们希望它扩大。这意味着,垂直约束必须掌握控制权:我们设置优先级明细集装箱的高度约束的东西很低(我用的250),所以它有利于内容视图中的制约因素被忽略

我不得不修改我的的UITableViewCell 子类来支持这些操作:

I had to modify my UITableViewCell subclass to support these operations:

// `showDetails` is exposed to control, whether the cell should be expanded
var showsDetails = false {
    didSet {
        detailViewHeightConstraint.priority = showsDetails ? lowLayoutPriority : highLayoutPriority
    }
}

override func awakeFromNib() {
    super.awakeFromNib()
    detailViewHeightConstraint.constant = 0
}

要触发的行为,我们必须重写的tableView(_:didSelectRowAtIndexPath方法:)

To trigger the behavior, we must override tableView(_:didSelectRowAtIndexPath:):

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: false)

    switch expandedIndexPath {
    case .Some(_) where expandedIndexPath == indexPath:
        expandedIndexPath = nil
    case .Some(let expandedIndex) where expandedIndex != indexPath:
        expandedIndexPath = nil
        self.tableView(tableView, didSelectRowAtIndexPath: indexPath)
    default:
        expandedIndexPath = indexPath
    }
}

请注意,我已经介绍了 expandedIndexPath 来跟踪我们目前扩大指数:

Notice that I've introduced expandedIndexPath to keep track of our currently expanded index:

var expandedIndexPath: NSIndexPath? {
    didSet {
        switch expandedIndexPath {
        case .Some(let index):
            tableView.reloadRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Automatic)
        case .None:
            tableView.reloadRowsAtIndexPaths([oldValue!], withRowAnimation: UITableViewRowAnimation.Automatic)
        }
    }
}

设置属性将导致表视图重装了合适的索引,给我们一个完美的机会来告诉细胞,它是否应该扩大:

Setting the property will result in the table view reloading the appropriate indexes, giving us a perfect opportunity to tell the cell, if it should expand:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExpandableTableViewCell

    cell.mainTitle = viewModel.mainTitleForRow(indexPath.row)
    cell.detailTitle = viewModel.detailTitleForRow(indexPath.row)

    switch expandedIndexPath {
    case .Some(let expandedIndexPath) where expandedIndexPath == indexPath:
        cell.showsDetails = true
    default:
        cell.showsDetails = false
    }

    return cell
}

最后一步是使自身在大小 viewDidLoad中()

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.contentInset.top = statusbarHeight
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 125
}

下面是结果:

细胞现在可以正确地调整大小自己。您可能会注意到动画还是有点不可思议,但是,这并不属于这一问题的范围固定。

Cells now correctly size themselves. You may notice that the animation is still a bit weird, but fixing that does not fall into the scope of this question.

这篇关于使用自动布局约束动态尺寸表视图细胞的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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