UILabel在UITableViewCell中使用自定义UIEdgeInsets截断

时间:2017-01-19 22:44:31

标签: ios swift uitableview autolayout uilabel

我有一个包含UILabel的单元格的UITableView。 UILabel有一个自定义的UIEdgeInset。我将UILabel子类化并将UIEdgeInsets设置为:

override func drawText(in rect: CGRect) {
    super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
}

override var intrinsicContentSize: CGSize {
    var contentSize = super.intrinsicContentSize
    contentSize.width += leftInset + rightInset
    contentSize.height += topInset + bottomInset
    return contentSize
}

但是当我在UILabel中有更多行时,标签会被截断。 我已将行高配置为 UITableViewAutomaticDimension 并设置 estimatedRowHeight 。约束也很好。 问题似乎在于我设置UIEdgeInsets,因为如果我不自定义它,它可以正常工作。

可能我应该告诉单元格在设置插入后更新约束,但到目前为止我无法做到这一点。

故事板中添加的约束。 BottomTopLeadingTrailing与超级视图(UITableViewCell)相关。所有常量都设置为0。

cellForRowAtIndexPath中,代码如下:

let cell = tableView.dequeueReusableCell(withIdentifier: "AnswersCell", for: indexPath) as! AnswerCell  
cell.answerLabel.text = alternatives[indexPath.row]
return cell

3 个答案:

答案 0 :(得分:3)

从故事板的属性检查器部分

设置UILable的这两个属性
  1. 排到0
  2. 换行换行
  3. 或者您也可以从代码中设置这些属性。

    self.answerLabel.numberOfLines = 0
    self.answerLabel.lineBreakMode = .byWordWrapping
    

    并将下面的代码放在UILable的子类

    class CustomLabel: UILabel {
    
    @IBInspectable var topInset: CGFloat = 5.0
    @IBInspectable var bottomInset: CGFloat = 5.0
    @IBInspectable var leftInset: CGFloat = 20.0
    @IBInspectable var rightInset: CGFloat = 5.0
    
    override func drawText(in rect: CGRect) {
        let insets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
        super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
    }
    
    override var intrinsicContentSize: CGSize {
        get {
            var contentSize = super.intrinsicContentSize
            contentSize.height += topInset + bottomInset
            contentSize.width += leftInset + rightInset
            return contentSize
        }
    }
    

    }

    试试这个。

    希望它对你有用..

答案 1 :(得分:1)

在多线标签的自动布局过程中,UILabel不使用其intrinsicContentSize属性提供的宽度计算其高度,而是使用preferredMaxLayoutWidth,但尚未对其进行调整以考虑您的内容插图。

UILabel的头文件为preferredMaxLayoutWidth提供以下注释:

  

//如果非零,则在为多行标签确定-intrinsicContentSize时使用此方法

在您的情况下,preferredMaxLayoutWidth的所需值是标签的自动布局宽度(即表格视图单元格的宽度)减去任何左右内容插入内容。设置该属性的最实用方法是在表视图单元子类中,因为这是在自动布局期间访问表视图单元格宽度的最直接的位置。

在为自定义表格视图单元格执行自动布局时,UITableView会在每个单元格上调用systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority)。 (参见WWDC 2014 Session 226。)传递给该方法的拟合大小是表格视图的宽度为零的宽度,水平拟合优先级为UILayoutPriorityRequired

因此,覆盖该方法并为preferredMaxLayoutWidth设置所需的值:

//  AnswerCell.swift

@IBOutlet weak var answerLabel: AnswerLabel!

override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
    answerLabel.preferredMaxLayoutWidth = targetSize.width - answerLabel.insets.left - answerLabel.insets.right
    return super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
}

效果是,在自动布局期间计算其高度时,UILabel使用已根据内容插入调整的值preferredMaxLayoutWidth,这可确保UITableView为其单元格获得正确的高度。

<强>附录

或者,您可以直接在表格视图单元格的内容视图中或通过将其嵌入内容视图的另一个子视图中,而不是上述所有内容,只需更改标签上的约束即可插入整个标签。

答案 2 :(得分:-2)

我将我的标签分类为:

class PaddingLabel: UILabel {

    var topInset: CGFloat = 0
    var bottomInset: CGFloat = 0
    var leftInset: CGFloat = 0
    var rightInset: CGFloat = 0

    override func drawText(in rect: CGRect) {
        let insets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
        super.drawText(in: UIEdgeInsetsInsetRect(rect, insets))
    }

    override var intrinsicContentSize: CGSize {
        get {
            var contentSize = super.intrinsicContentSize
            contentSize.height += topInset + bottomInset
            contentSize.width += leftInset + rightInset
            return contentSize
        }
    }
}

也许它是get失踪的。