如何自动调整包含多行UIButton的UITableViewCell的高度?

时间:2016-05-08 16:39:25

标签: ios swift uitableview uibutton

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 Bug报告#26170971。

该错误导致: enter image description here

3 个答案:

答案 0 :(得分:1)

您应该使用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中的错误?

答案 1 :(得分:1)

问题是内部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

答案 2 :(得分:0)

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