Pregunta

Estoy tratando de medir el tamaño visual de una NSString que tenga en cuenta el número de líneas que puedo representar. Sin embargo, sizeWithFont no tiene en cuenta la propiedad numberOfLines? Así que mi algoritmo de diseño posiciona todo lo más bajo de lo que realmente debe ser.

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
/// the follow code ignores numberOfLines and just tells me the size of the whole block.  
// I'd like it to be aware of numberOfLines
//
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
        lineBreakMode:UILineBreakModeWordWrap];

¿Alguien sabe cómo hacerlo usando el iPhone SDK?

¿Fue útil?

Solución

En lugar de CGFLOAT_MAX para la altura máxima de su cálculo de texto, intente obtener el tamaño de una línea con esto:

[_price.text sizeWithFont:_price.font].height

y luego multiplique eso por el número máximo de líneas que desea, luego conéctelo a la altura del tamaño al que se está limitando. Probablemente se vería así:

_price = [[UILabel alloc] init];
_price.text = myPriceValue;
_price.lineBreakMode = UILineBreakModeWordWrap;
_price.numberOfLines = 3;
_price.backgroundColor = [UIColor clearColor];
_price.textColor = TTSTYLEVAR(colorPrice);
CGFloat lineHeight = [_price.text sizeWithFont:_price.font].height;
CGSize priceSize = [_price.text sizeWithFont:_price.font
        constrainedToSize:CGSizeMake(maxWidth, lineHeight * _price.numberOfLines)
        lineBreakMode:UILineBreakModeWordWrap];

No use esto si alguna vez establece el número de líneas en 0, ya que su altura máxima será 0 en ese caso; deberías usar CGFLOAT_MAX entonces.

Otros consejos

Utilice sizeToFit de UILabel en lugar de sizeWithFont: para diseñar una UILabel multilínea, ya que sizeWithFont: truncará la cadena (consulte los documentos de Apple). El siguiente código reduce el tamaño de fuente de una etiqueta hasta que el texto se ajuste al tamaño especificado ... se usarán varias líneas de texto tan pronto como se ajusten a la altura especificada:

-(void)setFontSizeOfMultiLineLabel: (UILabel*)label 
        toFitSize: (CGSize) size 
        forMaxFontSize: (CGFloat) maxFontSize 
        andMinFontSize: (CGFloat) minFontSize 
        startCharacterWrapAtSize: (CGFloat)characterWrapSize{

CGRect constraintSize = CGRectMake(0, 0, size.width, 0);
label.frame = constraintSize;
label.lineBreakMode = UILineBreakModeWordWrap;
label.numberOfLines = 0; // allow any number of lines

for (int i = maxFontSize; i > minFontSize; i--) {

    if((i < characterWrapSize) && (label.lineBreakMode == UILineBreakModeWordWrap)){
        // start over again with lineBreakeMode set to character wrap 
        i = maxFontSize;
        label.lineBreakMode = UILineBreakModeCharacterWrap;
    }

    label.font = [label.font fontWithSize:i];
    [label sizeToFit];
    if(label.frame.size.height < size.height){
        break;
    }       
    label.frame = constraintSize;
  } 
}

Llámalo con una etiqueta que tenga tu texto y fuente favoritos:

UILabel *label = [[UILabel alloc] initWithFrame: CGRectZero];   
label.backgroundColor = [UIColor clearColor];   
label.textColor = [UIColor whiteColor];
label.text = text;
label.font = [UIFont fontWithName: @"Helvetica" size: 16];
[self setFontSizeOfMultiLineLabel: label toFitSize: CGSizeMake(200, 44) forMaxFontSize: 16 andMinFontSize: 8 startCharacterWrapAtSize: 11]; 

El parámetro startCharacterWrapAtSize le permite elegir usar characterWrap comenzando en el tamaño de fuente dado. Esto debería ahorrar espacio en el caso de que wordWrap use fuentes realmente pequeñas.

editar: corrección de errores

En lugar de intentar hacerlo en una llamada, haga algo como esto (perdone el pseudocódigo, es tarde):

NSString *s = _price.text;
UIFont *font = _price.font;
CGFloat fontSize = font.pointSize;

while (TRUE)
{
   CGSize priceSize = [s sizeWithFont: font constrainedToSize: 
       CGSizeMake(maxWidth, fontSize) lineBreakMode: UILineBreakModeWordWrap];

    if ( /* priceSize is satisfactory */ )
    {
        break; // Make sure this exits, eventually!!!
    }
    fontSize -= 1.0; // or a smaller decrement if you like
    font = // new, smaller font

}

La respuesta correcta es, por supuesto, que debe establecer numberOfLines en 0, lo que hará que el marco calcule el resultado con la cantidad de líneas que necesite. Consulte también esta pregunta .

Por supuesto que no lo tiene en cuenta, ya que nada de lo que se llama o se pasa tiene esa información. Estás trabajando estrictamente con cadenas, tamaños y fuentes. Es la etiqueta que tiene el número de líneas.

No estoy seguro de cuál es exactamente tu problema; ¿estás obteniendo una talla demasiado alta o demasiado corta, o qué? Puede averiguar el número de líneas de texto dividiendo la altura del resultado por la altura de la fuente, que es el valor del ascendente más el descendente, creo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top