首页 > 解决方案 > 如何在 swift 中创建动态自调整高度 UITableViewCell?

问题描述

嘿,我有一个 tableview 控制器,我想用标签和 ImageViews 创建动态单元格高度。我尝试了类似下面的方法,但它对我不起作用。关于代码的错误在哪里。任何的想法 ?

class NotificationsPageController: UITableViewController{

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(NotificationCell.self, forCellReuseIdentifier: notCell)
    view.backgroundColor = .black
    tableView.estimatedRowHeight = 60
}

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

    override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
      return 60
  }

 class NotificationCell: UITableViewCell {

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
      super.init(style: style, reuseIdentifier: reuseIdentifier)
   backgroundColor = UIColor(red: 18/255, green: 18/255, blue: 18/255, alpha: 1)

    setNotificationAnchors()

}

fileprivate func setNotificationAnchors() {

    addSubview(notiType)
    notiType.anchor(top: topAnchor, left: leftAnchor, bottom: nil, right: rightAnchor, paddingTop: 4, paddingLeft: 6, paddingBottom: 0, paddingRight: 20, width: 0, height: 0)
    //notiType.centerYAnchor.constraint(equalTo: notiImage.centerYAnchor).isActive = true



    addSubview(notiImage)
    notiImage.anchor(top: nil, left: nil, bottom: nil, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 4, width: 0, height: 0)
    notiImage.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true



}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
}

标签: swiftuitableviewdynamic

解决方案


首先,我强烈建议您了解约束和自动布局的工作原理。您发布的代码表明您正在使用一种.anchor(top:left:bottom:right:...)“约束帮助器”这一事实表明您还不了解它。

所以,这里是一个简单的例子。请注意,这不是一个完整的实现,但它应该让您朝着正确的方向前进:

class NotificationCell: UITableViewCell {

    let notiType: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        return v
    }()

    let notiImage: UIImageView = {
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        backgroundColor = UIColor(red: 18/255, green: 18/255, blue: 18/255, alpha: 1)

        setNotificationAnchors()

    }

    fileprivate func setNotificationAnchors() {

        contentView.addSubview(notiType)
        contentView.addSubview(notiImage)

        let g = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([

            // constrain label Top, Leading, Bottom to contentView margins
            notiType.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            notiType.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            notiType.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),

            // constrain image view Right and centerY to contentView margins
            notiImage.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            notiImage.centerYAnchor.constraint(equalTo: g.centerYAnchor, constant: 0.0),

            // guessing square (1:1 ratio) image view, 24 x 24
            notiImage.widthAnchor.constraint(equalToConstant: 24.0),
            notiImage.heightAnchor.constraint(equalTo: notiImage.widthAnchor),

            // leave 8-pts space between label and image view
            notiType.trailingAnchor.constraint(equalTo: notiImage.leadingAnchor, constant: -8.0),

        ])

        // during development, so we can easily see the element frames
        notiType.backgroundColor = .cyan
        notiImage.backgroundColor = .red

    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class ExampleTableViewController: UITableViewController {

    let notCell = "notCell"

    let theData: [String] = [
        "Single line label.",
        "This lable will have enough text that it will need to wrap onto multiple lines.",
        "Another single line cell.",
        "Here is a description of a table view cell: Defines the attributes and behavior of cells in a table view. You can set a table cell's selected-state appearance, support editing functionality, display accessory views (such as a switch control), and specify background appearance and content indentation.",
        "This is the fifth row.",
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(NotificationCell.self, forCellReuseIdentifier: notCell)
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return theData.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: notCell, for: indexPath) as! NotificationCell

        cell.notiType.text = theData[indexPath.row]

        // set image here...
        //cell.notiImage.image = ...

        return cell
    }

}

结果 - 多行标签(青色背景)和 24x24 图像(红色背景):

在此处输入图像描述

顺便说一句……关于这个的分步教程可以在很多很多地方找到 - 有点难以认为你搜索过并且找不到类似的东西。


推荐阅读