在 UITableView 中对齐多个运行时生成的 UILabel

Posted

技术标签:

【中文标题】在 UITableView 中对齐多个运行时生成的 UILabel【英文标题】:Aligning multiple runtime generated UILabels in a UITableView 【发布时间】:2017-01-03 09:00:43 【问题描述】:

我有一个UITableView,它需要通过列出类似的样式来支持内容

但棘手的部分是“标签”的数量会因每个单元格而异,有些可能只有 4 个,但也有最多 12 个。此外,“值”可以是单个单词或最多两行的短语(如上图所示)。所以我决定使用UIStackView 来帮助我打包和调整我的UILabels 用来显示这个的大小。当“标签”的长度不同时,我目前遇到了一个问题,例如:

即使“标签”的长度不同,我也需要像第一张图片一样对齐“值”的前端。 UIStackView 的行为是否允许这样做?或者是否有其他方法可以让我获得所需的结果?

注意:每个“标签”和“值”都在一个 UIStackView 中,我这样做是为了对齐它们。

我也尝试过使用字符串格式,但多于一行的“值”会包裹在标签下,而不是像我在图像中所做的那样自行包裹。

我尝试将所有“标签”放在一个 UIStackView 中,将所有“值”放在另一个中,一旦“值”超过一行,我就无法让它们像在图像中那样对齐。

或者,如果这可能是我在某个地方犯的错误,这就是我创建 UIStackViews 的方式:

    var higherCount = 0
    if labels.count<values.count 
        higherCount = values.count
     else 
        higherCount = labels.count
    

    mainStackView = UIStackView(frame: CGRect(x: 0, y: 0, width: frame.width, height: frame.height))

    for i in 0..<higherCount 
        var height:CGFloat = 20
        if (values[i] as NSString).size(attributes: [NSFontAttributeName:UIFont.systemFont(ofSize: UIFont.systemFontSize)]).width > frame.width 
            height = 42
        

        let stackViewToAdd = UIStackView(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))

        let label = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))
        if labels.count<higherCount 
            label.text = ""
         else 
            label.text = labels[i]
        
        label.setContentCompressionResistancePriority(1000, for: .horizontal)
        label.setContentHuggingPriority(999, for: .horizontal)
        stackViewToAdd.addArrangedSubview(label)
        let value = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: height))
        if values.count<higherCount 
            value.text = ""
         else 
            value.text = values[i]
        
        value.lineBreakMode = .byWordWrapping
        value.numberOfLines = 2
        stackViewToAdd.addArrangedSubview(value)
        mainStackView?.addArrangedSubview(stackViewToAdd)
    
    mainStackView?.alignment = .fill
    mainStackView?.axis = .vertical
    mainStackView?.distribution = .fill

【问题讨论】:

您可以使用自定义大小的表格视图单元格 @VinupriyaArivazhagan 你能解释更多吗?我尝试使用它,但因为我的整个单元格是通过编程方式创建的,所以单元格根本不会调整大小。 【参考方案1】:

如果您以编程方式创建了单元格,那么您可以根据 UILabel 内容的大小以编程方式调整单元格的大小。

在我的例子中Label字体是UIFont.systemFont(ofSize: 15),最小TableViewCell高度是50,arrLabel1arrLabel2将是Labels的内容。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return arrLable1.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = UITableViewCell(style: .default, reuseIdentifier: "\(indexPath.row)")

    let lable1 = UILabel(frame: CGRect(x: 10, y: 10, width: view.frame.size.width - 20, height: 0))
    lable1.numberOfLines = 0
    lable1.font = UIFont.systemFont(ofSize: 15)
    lable1.text = arrLable1[indexPath.row]
    lable1.sizeToFit()
    cell.addSubview(lable1)

    let lable2 = UILabel(frame: CGRect(x: 10, y: lable1.frame.origin.y + lable1.frame.size.height + 10 , width: view.frame.size.width - 20, height: 0))
    lable2.numberOfLines = 0
    lable2.font = UIFont.systemFont(ofSize: 15)
    lable2.text = arrLable2[indexPath.row]
    lable2.sizeToFit()
    cell.addSubview(lable2)

    return cell


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath)
    -> CGFloat 

    let boundingRect1 = arrLable1[indexPath.row].boundingRect(with: CGSize(width: view.frame.size.width - 40 , height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin,attributes:[ NSFontAttributeName : UIFont.systemFont(ofSize: 15)] ,context: nil)

    let boundingRect2 = arrLable2[indexPath.row].boundingRect(with: CGSize(width: view.frame.size.width - 40 , height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin,attributes:[ NSFontAttributeName : UIFont.systemFont(ofSize: 15)] ,context: nil)

    guard boundingRect1.height + boundingRect2.height + 30 > 50 else 
        return 50
    

    return boundingRect1.height + boundingRect2.height + 30

Label numberOfLines 设置为 0

【讨论】:

谢谢,这很有用,但它并没有解决我的问题。我遇到的主要问题是单元格中多个标签的对齐方式。我做了一些计算来设置单元格的高度,不过我会试试你的,看看它是否效果更好。但我需要在标签到值的关系中整齐地对齐内容。 设置Label1内容,设置Label1 sizeToFit(),从Label1获取frame。对所有标签执行相同操作。然后为所有标签设置“y”位置取决于标签框架。然后重新对齐框架。您可以使用上面的代码来获取 UITableViewCell 高度。 所以你建议我使用计算出的大小而不是使用UIStackView来计算每个标签的位置? 查看我更新的答案。在我看来 UIStackView 是没有必要的。 谢谢!我处理了您拥有的代码并对其进行了改进以支持多个 UILabel,就像我需要的那样,您可以查看并确认编辑吗?

以上是关于在 UITableView 中对齐多个运行时生成的 UILabel的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UITableViewCell 对齐到 UITableView 的底部?

UITableView 与导航栏不对齐(单元格在旋转时卡在下面)

UiViewController 内的 UITableView 不对齐中心

在 UITableView 中对齐图像

在 UITableView 中对齐行

GUI 对象在运行时位置和对齐不正确