from ios objective-c iphone ios8 xib
https://www.dropbox.com/s/sdahx9njnsxiv98/MultiLineUILabel.zip?dl=1

ios - from - main storyboard xcode



Ajuste automático añadiendo relleno extra en la parte superior e inferior de UILabel iPhone 6/6+cuando se establece preferredMaxLayoutWidth (9)

Creé un proyecto de muestra para reproducir esto.

Tengo un archivo xib con un UILabel que tiene una restricción fija, inicial y final. Agregué una restricción minHeight y establecí el número de líneas en 0.

Establecí el preferredMaxLayoutWidth en Automatic (marcado en el archivo xib).

En viewDidLoad, tengo esto:

self.myLabel.layer.borderColor = [[UIColor redColor] CGColor]; self.myLabel.layer.borderWidth = 2.0f;

self.myLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

Y cuando ejecuto el simulador en el iPhone 6 o 6+, obtengo esto:

No tengo idea de dónde viene ese relleno superior e inferior y es proporcional a la cantidad de caracteres en el UILabel que se muestra.

¿Hay alguna configuración mágica que olvidé? Funciona bien en dispositivos iPhone 4 ".

Ahora bien, si no configuro el MaxLayoutWidth preferido, no tiene el relleno adicional, pero esto rompe mis líneas múltiples en el UILabel. Corta el texto. No usé Size-Class.

Editar:

Así que cambié algunas cosas en mi proyecto de muestra para que coincida con la situación en mi proyecto real. He agregado un tableView (con las restricciones superior, principal, inferior y final establecidas en su vista principal). Cada celda en TableView tiene 4 etiquetas. La etiqueta superior tiene una restricción superior, principal y posterior a la vista de contenido de la celda y las etiquetas posteriores tienen una restricción vertical a la etiqueta que está sobre ella. Cada etiqueta tiene un conjunto de restricciones heightGreaterThan y un conjunto de widthGreaterThan.

Así es como se ve sin el conjunto preferredMaxLayoutWidth (Observe cómo las etiquetas están limitadas a 1 línea).

Con preferredMaxLayoutWidth. Ahora UILabel muestra todo el contenido, pero tiene un relleno en la parte superior e inferior.

Edit2: Proyecto de ejemplo: https://www.dropbox.com/s/sdahx9njnsxiv98/MultiLineUILabel.zip?dl=1


¿Hay alguna restricción en la parte inferior de la etiqueta? Creo que está permitiendo estirar debido a la prioridad de abrazo de contenido. Establézcalo en 1000 (requerido). Eso evitará que se expanda más allá de su tamaño de texto. Luego deberá agregar las restricciones adecuadas a la parte inferior de la etiqueta.


UILabel centra el texto verticalmente. Supongo que lo que está viendo es que sus restricciones están causando que la vista de la etiqueta se extienda en el dispositivo más grande, y el texto, como se espera, se centra verticalmente en la vista de tamaño.

Podría intentar usar un UITextView no editable con UIViewContentModeTop en su lugar.


Como necesitaba establecer preferredMaxLayoutWidth para compatibilidad con iOS 7, terminé llamando a boundingRectWithSize para calcular la altura de etiqueta requerida y establecer una constante de restricción de altura expuesta para UILabel.

CGRect labelRect = CGRectIntegral([myText boundingRectWithSize:size options:options attributes:attributes context:context]); self.myLabelHeightConstraint.constant = labelRect.size.height;


Entonces, lo que terminé haciendo fue crear una subclase para la etiqueta y anular setBounds: y establecer el preferredMaxLayoutWidth a sus límites.

- (void)setBounds:(CGRect)bounds { [super setBounds:bounds]; if (self.preferredMaxLayoutWidth != bounds.size.width) { self.preferredMaxLayoutWidth = bounds.size.width; [self setNeedsUpdateConstraints]; }}

Además, en la subclase UITableViewCell, anulo el layoutSubiews

- (void)layoutSubviews { [super layoutSubviews]; [self.contentView layoutIfNeeded]; // labelsCollection is an IBOutletCollection of my UILabel sublasses for (UILabel *label in self.labelsCollection) { label.preferredMaxLayoutWidth = label.bounds.size.width; }}

Esto funciona todo el tiempo. Creo que la razón de este extraño comportamiento es que UILabel está configurado inicialmente en 280px (320px - relleno en cada lado) en el archivo xib, pero durante el tiempo de ejecución, cambia su ancho para acomodar pantallas más grandes (ya que establecí el inicio y el final restricciones aumenta el ancho que cambia el ''preferredMaxLayoutWidth'' a un valor mayor). Por alguna razón, UILabel no actualiza su preferredMaxLayoutWidth al valor más grande y causa el espacio en blanco en la parte superior e inferior.

Esa es mi hipótesis

Espero que esto ayude.


Así que así es como lo implementé rápidamente, en la clase que extiende UILabel, anulo los límites var con un getter y setter, que establece los límites del super var y lo devuelve, de esta manera puedes agregar algún código al get y al set .

Debo decir que no estoy convencido de que esté haciendo toda la magia por el momento, todavía tengo grandes espacios abiertos.

override var bounds:CGRect { get { return super.bounds } set { super.bounds = newValue if (self.preferredMaxLayoutWidth != super.bounds.size.width) { self.preferredMaxLayoutWidth = super.bounds.size.width; self.setNeedsUpdateConstraints() } } }


Primero que nada chicos, perdón por mi inglés. Soy novato en inglés, pero trataré de describir cómo solucioné este problema.

Enfrenté este problema en algunos de mis proyectos. Entonces mi solución para arreglar esto es:

  1. En una celda tengo el siguiente método de configuración: - (void) configureWithSomeObject: parentViewSize: y en tableView: cellForRowAtIndexPath: Creé una celda como esta:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { YourCell *cell; //cell initialization [cell configureWithSomeObject:nil parentViewSize:tableView.frame.size]; return cell; }

  2. Los métodos de configuración internos simplemente establecen preferredMaxLayoutWidth según el ancho principal:

    - (void)configureWithSomeObject:(NSObject)someObject parentViewSize:(CGSize)parentViewSize { // do your stuff self.someLabel.preferredMaxLayoutWidth = parentViewSize.width; }

PD en caso de que tenga espacios iniciales / finales debe restarlo del valor parentViewSize.width.

Espero que sea útil para todos :)


Estaba teniendo un problema similar, y solo subclasificando el UILabel y reemplazando setBounds no funcionó para mí. Al pasar por setBounds , noté que la altura de la etiqueta era 39.999999993. Así que hice el siguiente cambio, para redondearlo a 40:

- (void)setBounds:(CGRect)bounds { bounds.size.height = ceilf(CGRectGetHeight(bounds)); [super setBounds: bounds]; if (self.preferredMaxLayoutWidth != bounds.size.width) { self.preferredMaxLayoutWidth = bounds.size.width; [self setNeedsUpdateConstraints]; } }

Esto me lo arregló, no más relleno extra por encima y por debajo de mi UILabel en dispositivos grandes. Tampoco tuve que establecer la prioridad de abrazo de contenido.


Cualquiera que esté investigando esta pregunta que ya esté utilizando maxPreferredLayoutWidth (por cierto, no es necesario crear una subclase, simplemente configúrelo en viewDidLayoutSubviews de su VC) verifique que esté configurando el ancho de la vista correcta.

El mío no funcionaba porque tenía:

label1.maxPreferredLayoutWidth = label1.frame.width label2.maxPreferredLayoutWidth = label1.frame.width

Cuando debería haber sido:

label1.maxPreferredLayoutWidth = label1.frame.width label2.maxPreferredLayoutWidth = label2.frame.width

¿Ves la diferencia? No lo hice por 3 horas jajaja


usar esta clase me lo arregló

import UIKit class CustomLabel: UILabel { override func drawText(in rect: CGRect) { if let stringText = text { let stringTextAsNSString = stringText as NSString let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil).size super.drawText(in: CGRect(x: 0, y: 0, width: self.frame.width, height: ceil(labelStringSize.height))) } else { super.drawText(in: rect) } } }