如何使用自动调整其高度的 SnapKit 以编程方式创建 UITableViewCell?

Posted

技术标签:

【中文标题】如何使用自动调整其高度的 SnapKit 以编程方式创建 UITableViewCell?【英文标题】:How to create programatically UITableViewCell using SnapKit that autoresized its height? 【发布时间】:2019-04-30 12:05:02 【问题描述】:

看似简单的事情却变得非常困难。我已经在这里和 SnapKit GitHub 上浏览了多个主题,但未能解决我的问题。

我想让UITableViewCell 带有一个位于中间的标签,假设从单元格的顶部和底部开始都是 50。

值得一提的是,单元格是以编程方式创建的

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.addSubview(titleLabel)
    titleLabel.snp.makeConstraints  (make) -> Void in
        make.topMargin.equalToSuperview().offset(50.0)
        make.left.equalToSuperview().inset(UIView.getValueScaledByScreenWidthFor(baseValue:10.0))
        make.bottomMargin.equalToSuperview().offset(50.0)

    

在 ViewController 中,我尝试了自动单元格高度的两种方法:

 extension EpisodeViewController: UITableViewDelegate 
  func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat 
    return UITableViewAutomaticDimension
  

tableView.estimatedRowHeight = 100
tableView.rowHeight = UITableViewAutomaticDimension

viewDidLoad()方法中

我得到的是:

这三个单元格中的每一个都应填充“测试” - 相反,它已将相应单元格下方的标签向下推而不调整单元格的大小。

尝试了许多不同的组合,例如:

1) 将约束优先级设置为 999 - 无变化

2) 添加到 contentView 而不是 self - 根本不显示

3) 使用 top 而不是 topMargin 等 - 没有区别

你能告诉我这段代码有什么问题吗?在以编程方式创建的单元格中使用 SnapKit 时的一般经验法则是什么?应该根据约束自动调整其高度?

提前致谢

编辑

UITableViewDataSource 方法

extension EpisodeViewController: UITableViewDataSource 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell: EpisodeHeaderCell = tableView.dequeueReusableCell(for: indexPath)
    cell.viewModel = viewModel
    return cell


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 3

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



【问题讨论】:

你有没有尝试给 UILabel 指定大小的字体? @EmreÖnder 是的,我没有粘贴这部分代码,但您可以看到字体大小大于系统 你能把cellForRowAt的代码贴出来吗? @CerlinBoss 当然,请参阅我编辑的问题,谢谢。 【参考方案1】:
    label.snp.makeConstraints 
        $0.left.equalToSuperview().offset(10)
        $0.right.equalToSuperview().offset(-10)
        $0.top.equalToSuperview().offset(50)
        $0.bottom.equalToSuperview().offset(-50)
    

这里是 viewController.swift 文件的全部代码。

class TestCell: UITableViewCell 
    static let identifier: String = "test_cell_identifier"

    var label: UILabel!

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.configure()
    

    func configure() 
        label = UILabel(frame: .zero)
        self.contentView.addSubview(label)
        label.snp.makeConstraints 
            $0.left.equalToSuperview().offset(10)
            $0.right.equalToSuperview().offset(-10)
            $0.top.equalToSuperview().offset(50)
            $0.bottom.equalToSuperview().offset(-50)
        
    

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


class ViewController: UIViewController 
    var data: [String] = [
        "Test1",
        "Test2",
        "Test3"
    ]

    var tableView: UITableView!

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView = UITableView(frame: .zero)
        self.view.addSubview(tableView)
        tableView.snp.makeConstraints 
            $0.edges.equalToSuperview()
        
        tableView.register(TestCell.self, forCellReuseIdentifier: TestCell.identifier)
        tableView.dataSource = self
        tableView.delegate = self

        tableView.estimatedRowHeight = 100
    


extension ViewController: UITableViewDelegate, UITableViewDataSource 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return data.count
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: TestCell.identifier, for: indexPath) as! TestCell
        cell.label.text = data[indexPath.item]
        return cell
    

【讨论】:

谢谢,但我认为它与 ViewModel 无关,也不是我通过问题标题中解释的故事板添加的。 你试过了吗? cell.layoutIfNeeded() 我回答了所有可能的情况来帮助你解决它。 cell.layoutIfNeeded() 应该可以工作。你为什么给我的答案minus 不幸的是,我可以取消这次投票,但请编辑您的答案以匹配问题(没有故事板) @LiJin - 你的代码有效,但有几个问题... 1) self.addSubview(label) 应该是contentView.addSubview(label) ... 2) tableView.rowHeight = UITableView.automaticDimension 是默认值,所以不需要... 3 ) tableView.estimatedRowHeight 不应该是 UITableView.automaticDimension - 它应该是一个估计值,在这种情况下,120 是合理的...... 4) 不要打电话给cell.layoutIfNeeded()【参考方案2】:

UITableViewCell 的 contentView 应该用于添加自定义视图

所以试试这样的东西(我还没有测试过)

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    self.contentView.addSubview(titleLabel)

    titleLabel.snp.makeConstraints  (make) -> Void in
        // Changed from bottom to top
        make.top.equalTo(self.contentView.snp.top).offset(50)
        make.bottom.equalTo(self.contentView.snp.bottom).offset(50)
        make.left.equalTo(self.contentView.snp.left)
        make.right.equalTo(self.contentView.snp.right)
    

【讨论】:

@DCDC 抱歉,代码中有错误。很可能它现在应该可以工作了。我已经在我所做的更改上添加了 cmets 好的,明白了,但现在它看起来与原始帖子中的图片几乎相同 - 标签超出了单元格,保持不变

以上是关于如何使用自动调整其高度的 SnapKit 以编程方式创建 UITableViewCell?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SnapKit 中设置 heightAnchor 的乘数 - swift

自动调整UICollectionView高度以调整其内容大小

Swift SnapKit 动态高度问题

iframe 自动调整其高度以适应内容高度

使用 SnapKit 自动调整 UILabel 大小

如何使节标题中的 UITextView 将其高度调整为其内容