【问题标题】:How to automatically adapt height of UITableViewCell containing a multiline UIButton?如何自动调整包含多行 UIButton 的 UITableViewCell 的高度?
【发布时间】:2016-09-03 06:55:25
【问题描述】:

UITableViewCell 的子类包含带有多行文本的UIButton,即属性numberOfLines = 0

表格视图单元格的高度不同,因此单元格高度设置为UITableViewAutomaticDimension

当添加带有多个文本行的UILabel 时,单元格高度会调整。但是它不适应UIButton,实际上按钮的框架也不适应其titleLabel的框架。

如何使表格视图单元格及其内容视图适应按钮高度?

class MyButtonCell: UITableViewCell {

    var button: UIButton!
    var buttonText: String?

    convenience init(buttonText: String?) {
        self.init()

        self.buttonText = buttonText

        button = UIButton(type: UIButtonType.System)
        button.titleLabel?.numberOfLines = 0
        button.titleLabel?.lineBreakMode = .ByWordWrapping
        button.contentHorizontalAlignment = .Center
        button.titleLabel?.textAlignment = .Center

        button.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubView(button)

        NSLayoutConstraint.activateConstraints([
            button.topAnchor.constraintEqualToAnchor(self.contentView.topAnchor),
            button.bottomAnchor.constraintEqualToAnchor(self.contentView.bottomAnchor),
            button.rightAnchor.constraintEqualToAnchor(self.contentView.rightAnchor),
            button.leftAnchor.constraintEqualToAnchor(self.contentView.leftAnchor)
            ])

        button.setTitle(buttonText, forState: .Normal)
        button.setTitleColor(buttonTextColor, forState: UIControlState.Normal)
        button.titleLabel?.font = buttonFont
    }
}

单元格高度通过以下方式自动计算:

tableView.estimatedRowHeight = 100

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

更新:

https://github.com/mtrezza/ButtonCellHeightBug上的示例项目

已提交 Apple 错误报告 #26170971。

该错误导致:

【问题讨论】:

  • 你在使用故事板和自动布局吗?
  • 知道了。设置文本后,在按钮上尝试 sizeToFit()。
  • @Siriss 试过没有成功:-/
  • 您是在使原型单元出队,还是为每个 indexPath 创建一个新单元?

标签: ios swift uitableview uibutton


【解决方案1】:

表格视图单元格的完全动态高度可通过以下方式实现:1)使用估计的行高,2)将 rowHeight 设置为 AutoDimension,3)最重要的是使用 xib/storyboard 中的约束。单元格可以包含按钮/标签或您想要的任何 UI 组件,只要您正确地约束它们,特别是要确保事物受到垂直约束,以便表格视图可以计算单元格高度。而且这样你就不用计算动态文本的高度,不需要sizeToFit/sizeThatFit,它适用于不同的屏幕尺寸。

【讨论】:

  • 感谢您的回答,@Siriss 能够重现我的问题,请参阅上面的答案。这种情况下的表格和单元格不是在情节提要中设计的,而是在使用自动布局的代码中设计的。表格视图单元格中单个按钮的 4 个必要约束非常简单,见上文。高度仍然适用于多行标签,但不适用于按钮。我认为这是因为没有直接设置按钮的文本而是使用setTitle:forState,因此标签高度约束/框架设置得太晚,并且单元格的高度是根据没有文本的titleLabel计算的。
  • 好的,现在我看到了困难。 UILabel 尊重 numberOfLines,但 UIButton 往往在一行中,除非您进行一些计算并显式设置框架,这很乏味。如果布局是一个障碍,只需使用 UILabel - 正确布局更容易 - 并添加手势识别器以使其可点击。
【解决方案2】:

您应该使用estimatedHeightForRowAtIndexPath。在您的按钮上,您可以调用sizeToFit(),它将调整其大小以包含文本。

另外,如果您在 tableView 上设置估计大小(如您所做的那样),您通常不需要调用 heightForRowAtIndexPathestimatedHeightForRowAtIndexPath,tableView 会为您设置。

编辑:

我创建了一个测试项目,您似乎是正确的。使用 UIButton setTitle 不会调整单元格的大小。

一种解决方法是使用heightForRowAtIndexPath 中的标签进行计算,然后返回该值+任何填充。然后在cellForRowAtIndexPath中,你仍然可以在按钮上设置标题,它就会出现。

//paragraphs is just a string array.
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        let label = UILabel(frame: CGRectMake(0,0,tableView.frame.width, <your prototype height>))
        label.numberOfLines = 0
        label.text = paragraphs[indexPath.row]
        label.sizeToFit()
        print(label.frame.height)
        return label.frame.height
    }

iOS 中的错误?

【讨论】:

  • 表格视图属性estimatedRowHeightrowHeight 必须设置为自动计算单元格高度。因此,因为未设置属性,所以方法 heightForRowAtIndexPath 被覆盖。表视图属性可与 AFAIK 方法互换。所以这似乎很好。
  • 没有指定的 heightForRow 会覆盖 tableview.estimatedRowHeight。如果您在 tableView 上设置了估计高度,则不需要调用 height 或estimatedHeight 委托方法,因为 tableView 会为您处理它。您必须使用 AutoLayout 并设置足够的约束来提供足够的信息来绘制单元格。
  • 你确定吗?苹果确实说:“要启用自动调整表格视图单元格,您必须将表格视图的 rowHeight 属性设置为 UITableViewAutomaticDimension。您还必须为estimatedRowHeight 属性分配一个值。一旦设置了这两个属性,系统就会使用自动布局来计算行的实际高度。” developer.apple.com/library/ios/documentation/UserExperience/…
  • 该链接说在 tableView 上设置 rowHeight 属性,而不是调用 heightForRowAtIndexPath 委托。在 tableView 上设置 tableView.rowHeighttableView.estimatedRowHeight 属性并删除您的 heightForRowAtIndexPath 看看会发生什么。另外,我从来没有设置过tableView.rowHeight 属性,以前也没有遇到过问题。
  • 感谢您迄今为止的意见。我发现绝对有必要设置这两个属性,否则自动调整大小根本不起作用,文档也清楚地说明了这一点。根据文档,属性和方法也可以互换,唯一的区别是使用tableView:heightForRowAtIndexPath:而不是rowHeight的性能影响。再一次,单元格高度正确地适应了 UILabels 和 UIImageViews。我只有 UIButton 才有这个问题。
【解决方案3】:

问题是内部UIButtonLabel 正确调整大小,但实际UIButton 没有。

我通过扩展 UIButton 并覆盖了一些东西来解决这个问题:

override func layoutSubviews() {
    super.layoutSubviews()
    self.titleLabel?.preferredMaxLayoutWidth = self.titleLabel?.frame.size.width ?? 0
}

override var intrinsicContentSize: CGSize {
    return self.titleLabel?.intrinsicContentSize ?? CGSize.zero
}

您还需要确保titleLabel?.numberOfLines = 0titleLabel?.lineBreakMode = .byWordWrapping

【讨论】:

  • 这是正确答案。我有时还添加了我自己的高度约束,将按钮高度与标签高度 + 一个常数联系起来。
猜你喜欢
  • 2019-07-29
  • 2011-03-05
  • 1970-01-01
  • 2015-03-25
  • 1970-01-01
  • 2016-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多