UILabel con ttwigs UIEdgeInsets personalizadas en UITableViewCell

Tengo una UITableView con celdas que contiene una UILabel. El UILabel tiene un UIEdgeInset personalizado. Subclasé el UILabel y configuré UIEdgeInsets así:

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 } 

Pero la label se trunca a veces cuando tengo más líneas en el UILabel. Ya he configurado el alto de fila para UITableViewAutomaticDimension y establezco theRowHeight estimado . También las restricciones están bien. El problema parece ser cuando estoy configurando UIEdgeInsets, ya que funciona bien si no lo personalizo.

Probablemente debería decirle a la célula que actualice las restricciones después de configurar las inserciones, pero no pude hacer esto hasta ahora.

Las restricciones donde se agrega en el guión gráfico. Bottom , Top , Leading y Trailing se relacionan con la supervisión (UITableViewCell). Todas las constantes se establecen en 0.

En cellForRowAtIndexPath el código es el siguiente:

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

Establezca estas dos properties de UILable desde la sección del inspector de Atributos del guión gráfico.

  1. Líneas a 0
  2. Salto de línea a wrap de palabras

o también puede establecer estas properties desde el código.

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

y coloque el código debajo en la subclass de 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 } } 

}

testing esto.

Espero que funcione para ti …

Durante el layout automático de una label multilínea, UILabel no calcula su altura utilizando el ancho proporcionado por su propiedad intrinsicContentSize , sino que usa prefernetworkingMaxLayoutWidth , que no se ha ajustado para tener en count las inserciones de contenido.

El file de encabezado para UILabel proporciona el siguiente comentario para prefernetworkingMaxLayoutWidth :

// Si no es cero, esto se usa cuando se determina -intrinsicContentSize para tags de varias líneas

En su caso, el valor deseado para prefernetworkingMaxLayoutWidth es el ancho de layout automático de la label (es decir, el ancho de la celda de vista de tabla) less las inserciones de contenido izquierdo y derecho. La forma más práctica de establecer esa propiedad se encuentra en la subclass de la celda de vista de tabla, ya que es el lugar más sencillo para acceder al ancho de la celda de vista de tabla durante el layout automático.

Al realizar un layout automático para las celdas de vista de tabla autodimensionadas, UITableView llama systemLayoutSizeFitting systemLayoutSizeFitting(_:withHorizontalFittingPriority:verticalFittingPriority) en cada celda. (Consulte la Sesión 226 de WWDC 2014 ). El tamaño de ajuste que se pasa a ese método es el ancho de la vista de tabla con una altura cero, y la prioridad de ajuste horizontal es UILayoutPriorityRequinetworking .

Por lo tanto, anule ese método y establezca el valor deseado para prefernetworkingMaxLayoutWidth :

 // AnswerCell.swift @IBOutlet weak var answerLabel: AnswerLabel! override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize { answerLabel.prefernetworkingMaxLayoutWidth = targetSize.width - answerLabel.insets.left - answerLabel.insets.right return super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority) } 

El efecto es que al computar su altura durante el layout automático, UILabel usa un valor de MaxMayoutWidth prefernetworkingMaxLayoutWidth que se ha ajustado para sus inserciones de contenido, lo que asegura que UITableView reciba las alturas correctas para sus celdas.

Apéndice

Como alternativa, en lugar de todo lo anterior, simplemente puede cambiar las restricciones en su label para insert la label completa, ya sea directamente en la vista de contenido de la celda de vista de tabla o incrustándola en otra subvista de la vista de contenido.

Subclasifiqué mi label de esta manera:

 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 } } } 

Tal vez sea el resultado que falta.