如何创建UITableView标题,其高度由其标签的高度决定?

TIM*_*MEX 12 ios swift

我想在tableView中添加一个标题.此标头包含1个UILabel.标题高度应根据标签所具有的行数计算.

在我的代码中,我正在添加标签<>标头的所有边缘的约束.这是我的尝试:

    //Add header to tableView
    header = UIView()
    header.backgroundColor = UIColor.yellowColor()
    tableView!.tableHeaderView = header

    //Create Label and add it to the header
    postBody = UILabel()
    postBody.text = "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog."
    postBody.font = UIFont(name: "Lato-Regular", size: 16.0)
    postBody.numberOfLines = 0
    postBody.backgroundColor = FlatLime()
    header.addSubview(postBody)

    //Enable constraints for each item
    postBody.translatesAutoresizingMaskIntoConstraints = false
    header.translatesAutoresizingMaskIntoConstraints = false

    //Add constraints to the header and post body
    let postBodyLeadingConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
    postBodyLeadingConstraint.active = true

    let postBodyTrailingConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
    postBodyTrailingConstraint.active = true


    let postBodyTopConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
    postBodyTopConstraint.active = true


    let postBodyBottomConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
    postBodyBottomConstraint.active = true


    //Calculate header size
    let size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
    var frame = header.frame
    frame.size.height = size.height
    header.frame = frame
    tableView!.tableHeaderView = header
    header.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)

这是我的表:

    let nib = UINib(nibName: "MessagesTableViewCell", bundle: nil)
    let nibSimple = UINib(nibName: "SimpleMessagesTableViewCell", bundle: nil)
    self.tableView!.registerNib(nib, forCellReuseIdentifier: "MessagesTableViewCell")
    self.tableView!.registerNib(nibSimple, forCellReuseIdentifier: "SimpleMessagesTableViewCell")
    self.tableView!.dataSource = self
    self.tableView!.delegate = self
    self.tableView!.rowHeight = UITableViewAutomaticDimension
    self.tableView!.estimatedRowHeight = 100.0
    self.tableView!.separatorStyle = UITableViewCellSeparatorStyle.None
    self.tableView!.separatorColor = UIColor(hex: 0xf5f5f5)
    self.tableView!.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
    self.tableView!.clipsToBounds = true
    self.tableView!.allowsSelection = false
    self.tableView!.allowsMultipleSelection = false
    self.tableView!.keyboardDismissMode = .OnDrag
Run Code Online (Sandbox Code Playgroud)

如您所见,标题没有考虑标签的高度(我做了numberOfLines = 0)

标题不会自动高度

ste*_*yde 13

UILabel利用UIView's intrinsicContentSize()来告诉自动布局应该是什么尺寸.但是,对于多行标签,内在内容大小不明确; 桌子不知道它是否应该短而宽,高而窄,或者介于两者之间.

为了解决这个问题,UILabel有一个叫做的财产preferredMaxLayoutWidth.设置它会告诉多线标签它应该最多宽度,并允许intrinsicContentSize()找出并返回适当的高度以匹配.通过不在preferredMaxLayoutWidth示例中设置,标签使其宽度不受限制,因此计算长单行文本的高度.

唯一的复杂因素preferredMaxLayoutWidth是,在自动布局为您计算一个宽度之前,您通常不知道标签的宽度.因此,在视图控制器子类中设置它的位置(它看起来像您的代码示例可能来自)位于viewDidLayoutSubviews:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    postBody.preferredMaxLayoutWidth = CGRectGetWidth(postBody.frame)
    // then update the table header view
    if let header = tableView?.tableHeaderView {
        header.frame.size.height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height
        tableView?.tableHeaderView = header
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,您需要为postBody标签添加一个属性才能生效.

如果您不在UIViewController此处的子类中,请告诉我,我将编辑我的答案.


Bes*_*rov 10

使用故事板实现

  1. UItableView附加上UITableViewCell新的UIView,让他UILabel 通过自动布局将它们连接
  2. UILabel把行数为0.
  3. ViewDidLoadUILabel的方法中调用一个方法sizeToFit() 并指定一个大小UIView,这将是你的HeaderVewheaderView.frame.size.height = headerLabel.frame.size.height

    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var headerView: UIView!
    @IBOutlet weak var headerLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        headerLabel.text = "tableViewdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarningdidReceiveMemoryWarning"
        headerLabel.sizeToFit()
        headerView.frame.size.height = headerLabel.frame.size.height
    }
Run Code Online (Sandbox Code Playgroud)

截图

在此输入图像描述

TestProject

测试项目链接


Sul*_*han 9

我们遇到的第一个问题是无法通过autolayout调整标题大小,有关详细信息,请参阅是否可以将AutoLayout与UITableView的tableHeaderView一起使用?

因此,我们必须手动计算标题的高度,例如:

@IBOutlet var table: UITableView!

var header: UIView?
var postBody: UILabel?

override func viewDidLoad() {
    super.viewDidLoad()

    let header = UIView()
    // don't forget to set this
    header.translatesAutoresizingMaskIntoConstraints = true
    header.backgroundColor = UIColor.yellowColor()

    let postBody = UILabel()
    postBody.translatesAutoresizingMaskIntoConstraints = false
    postBody.text = "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog."
    postBody.font = UIFont.systemFontOfSize(16.0)

    // don't forget to set this
    postBody.lineBreakMode = .ByWordWrapping
    postBody.numberOfLines = 0

    header.addSubview(postBody)

    let leadingConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
    let trailingConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
    let topConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
    let bottomConstraint = NSLayoutConstraint(item: postBody, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: header, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

    header.addConstraints([leadingConstraint, trailingConstraint, topConstraint, bottomConstraint])

    self.table.tableHeaderView = header

    self.header = header
    self.postBody = postBody
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let text = postBody!.attributedText!

    let height = text.boundingRectWithSize(
        CGSizeMake(table.bounds.size.width, CGFloat.max),
        options: [.UsesLineFragmentOrigin],
        context: nil
    ).height

    header!.frame.size.height = height
}
Run Code Online (Sandbox Code Playgroud)

您可能还想在stefandouganhyde的答案中使用该代码.你如何计算高度并不重要.关键是自动布局不会自动生效tableHeaderView.

结果:

结果表