【问题标题】:UITableViewCell height with dynamic subview swiftUITableViewCell 高度与动态子视图 swift
【发布时间】:2018-04-09 20:53:06
【问题描述】:

我有一个UITableViewUITableViewCell 有一个动态的UILabel,它将根据我从数据库中获得的数据添加。

我正在使用类似的东西

let testing = ["A", "B", "C", "D"] // This array is dynamic data
self.dictionaryTableView.estimatedRowHeight = 44
self.dictionaryTableView.rowHeight = UITableViewAutomaticDimension

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "vocabCell", for: indexPath)
    var y = 0
    for var i in 0..<self.testing.count {
        let lbl = UILabel(frame: CGRect(x: 0, y: y, width: 50, height: 25))
        lbl.text = self.testing[i]
        lbl.numberOfLines = 0
        cell.addSubview(lbl)
        y += 20       
    }
    return cell
}

UITableViewCell 高度不会自动拉伸以显示所有内容单元格。请帮忙 这是结果

编辑我在 UITableView cellForRowAtIndexPath 中为 uilabel 添加了约束,约束正在起作用(我在消耗单元格高度时就知道了),但单元格高度不会自动伸展

var bottomAnchor: NSLayoutYAxisAnchor = NSLayoutYAxisAnchor()
for var i in 0..<self.testing.count {
    let lbl = UILabel()
    lbl.text = self.testing[i]
    lbl.numberOfLines = 0
    lbl.translatesAutoresizingMaskIntoConstraints = false

    cell.addSubview(lbl)
    lbl.leftAnchor.constraint(equalTo: cell.leftAnchor, constant: 16).isActive = true
    lbl.widthAnchor.constraint(equalTo: cell.widthAnchor).isActive = true
    lbl.heightAnchor.constraint(equalToConstant: 25).isActive = true

    if i == 0 {
        lbl.topAnchor.constraint(equalTo: cell.topAnchor).isActive = true
    } else {
        lbl.topAnchor.constraint(equalTo: bottomAnchor).isActive = true
    }
    bottomAnchor = lbl.bottomAnchor
}
return cell

非常感谢

【问题讨论】:

  • 为什么要添加多个标签?我的意思是你可以插入下一行字符
  • @user3783161 在 cellForRowAt 内循环不是一个好主意,您可以添加标签、情节提要中的视图。您是否在 Google 上搜索过您的疑问?
  • @user3783161 关注这个问题,因为你有类似的问题。 stackoverflow.com/questions/18600047/…
  • @SPatel : 我需要多个 uilabel 因为每个标签都有一些特殊的属性(例如:显示在右侧,点击它会执行一个动作),不能只在一个标签中完成。有些数据有这些属性,有些数据没有。

标签: ios swift uitableview


【解决方案1】:

使用了这个代码。

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

【讨论】:

  • 1.不需要标签高度的大于或等于约束。 2. 这些并不是所有必要的步骤。
  • 这已经过时了,因为问题中的代码示例已经设置了self.dictionaryTableView.rowHeight = UITableViewAutomaticDimension
【解决方案2】:

您需要在实施中解决两件事:

  1. 创建单元格的布局tableView(_:, cellForRowAt:) 中将其出列。

    出于效率原因,表格视图在用户滚动时一遍又一遍地重用相同的单元格。这就是为什么您使用这种奇怪的“出队”功能而不是简单地实例化一个新单元格的原因。

    let cell = tableView.dequeueReusableCell(withIdentifier: "vocabCell", for: indexPath)
    

    将始终尝试返回刚刚滚动出视图的已使用单元格。仅当没有可用的回收单元格时(例如,将前几个单元格出列时),表格视图才会创建单元格的新实例。

    单元格的回收正是您应该从不tableView(_:, cellForRowAt:) 中创建单元格布局的原因,例如通过添加标签。重复使用单元格时,将在您之前添加的标签之上添加另一个标签,当第二次重复使用时,您将得到三个重叠的标签等。

    这同样适用于约束。当您在tableView(_:, cellForRowAt:) 的单元格中添加约束而不删除现有约束时,用户滚动时会添加越来越多的约束,很可能导致严重的约束冲突。

    相反,出列之前设置单元格的布局。有几种方法可以实现这一点:

    • 如果您在情节提要中使用UITableViewController,则可以创建动态原型并直接在情节提要中布置单元格。例如,您可以将标签拖到那里的原型单元格,并在自定义 UITableViewCell 子类中为其创建一个出口。

    • 您可以为您的单元创建一个 XIB 文件,在 Interface Builder 中打开它并在那里创建您的布局。同样,您需要使用适当的 outlet 创建一个 UITableViewCell 子类,并将其与您的 XIB 文件相关联。

    • 您可以创建一个UITableViewCell 子类并纯粹在代码中设置布局,例如在单元格的初始化程序中。

  2. 您需要使用自动布局。

    如果您在 Interface Builder 中创建布局,则只需添加必要的约束即可。如果您在代码中创建布局,则需要将您希望约束的所有视图的translatesAutoresizingMaskIntoConstraints 属性设置为false,例如:

    lbl.translatesAutoresizingMaskIntoConstraints = false
    

    在您的特定布局中,您需要使用单元格的contentView 的相应边缘将标签限制在左侧、右侧、顶部和底部。

    如果您不知道如何操作,请阅读 Apple 的 Auto Layout Guide。 (在 Interface Builder 中而不是在代码中执行此操作通常是一个更好的主意。)

    关于如何使用“用于动态单元格布局和可变行高的 UITableView 中的自动布局”的非常详细的描述可以找到here

【讨论】:

  • 我添加了约束(请参阅已编辑),但无法正常工作,是否有问题
  • 您的代码中还有其他一些我一开始忽略的错误。我更新了我的答案并添加了有关如何解决此问题的详细说明。
  • 感谢您提供的详细信息,还有一个问题。如果我在出队之前设置单元格布局,我该如何创建动态 UILabel,因为我不知道需要使用多少标签
  • 您只需将 text 分配给tableView(_:,cellForRowAt:) 内的标签。当标签根据文本和约束计算其内在内容大小时,其他一切都会自动发生。您唯一需要确保的是将标签的 numberOfLines 设置为 0(您已经在示例代码中这样做了)。这也应该在设置期间完成。
【解决方案3】:

您可以使用 UITableView 部分来呈现数据,而不是以编程方式添加视图。示例如下:

class ViewController: UITableViewController {

    private var dataSectionOne = ["Data 1", "Data 2"]
    // This can be your dynamic data. 
    // Once the data changed, called tableView.reloadData() to update the view.
    private var dataSectionTwo = ["A", "B", "C"] 

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
    }

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            return dataSectionOne.count
        } else if section == 1 {
            return dataSectionTwo.count
        }
        return 0
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        if indexPath.section == 0 {
            cell.textLabel?.text = dataSectionOne[indexPath.row]
        } else if indexPath.section == 1 {
            cell.textLabel?.text = dataSectionTwo[indexPath.row]
        }
        return cell
    }

}

结果:

【讨论】:

  • 感谢您的建议。我的表格视图有动态部分,每个部分都有我想使用 UILabel 来实现的数据
【解决方案4】:

我找到了答案here

我使用以下代码在 UITableViewCell 底部添加了一个约束,它正在工作,但我不知道这条线到底在做什么(我也不知道参数)

谁能帮我解释一下这段代码

let bottomSpaceConstraint: NSLayoutConstraint = NSLayoutConstraint(item: lbl, attribute: NSLayoutAttribute.bottomMargin, relatedBy: NSLayoutRelation.equal, toItem: cell.contentView, attribute: NSLayoutAttribute.bottomMargin, multiplier: 1, constant: -8)
cell.contentView.addConstraint(bottomSpaceConstraint)

【讨论】:

    猜你喜欢
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多