2012-06-22 9 views
5

Tengo 4 líneas UILabel con el marco y la fuente exactos.¿Cómo saber si NSString encaja en UILabel o no y el índice de la última cadena que cabe?

Necesito saber si esta cadena se ajusta a la etiqueta y cuál es el índice del último carácter que cabe.

+3

Esta pregunta debe ayudarle a: http://stackoverflow.com/questions/6422742/how-to-know-the-length-of-nsstring-that-fits-a-uilabel-with-fixed-size –

+0

Lo había visto primero, pero no ayudó –

+0

la respuesta @ Cupcake publicada aquí debería ayudarlo –

Respuesta

8

El núcleo de la respuesta está en la publicación mencionada de Cupcake. De todas formas, puede usar sizeWithFont:constrainedToSize:lineBreakMode: para descubrir cuál sería el tamaño de un marco con una fuente particular en una etiqueta de un ancho dado dado un ajuste específico de palabra, p. Ej.

CGSize size = [string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:UILineBreakModeWordWrap]; 

Set sizeConstraint a tener la misma anchura de la etiqueta, pero fijar la altura a ser más grandes. Si el size.height resultante es más grande que su UILabel, entonces su cadena es demasiado larga. Teóricamente, podría eliminar el último carácter/palabra e intentar nuevamente y repetir hasta que encaje.

Si cree que las cadenas pueden ser muy largas, es posible que desee ir hacia el otro lado, comenzar con una porción corta de la cadena y seguir agregando caracteres hasta que sea demasiado grande, y luego conocer el último carácter.

De cualquier forma, este cálculo iterativo del tamaño puede ser una operación bastante intensiva de la CPU, así que tenga cuidado.

Actualización:

Aquí es un algoritmo que devuelve la longitud de NSString que puede caber en la UILabel en cuestión utilizando la fuente por defecto (pero ignorando el tamaño mínimo de la letra):

- (NSUInteger)fitString:(NSString *)string intoLabel:(UILabel *)label 
{ 
    UIFont *font   = label.font; 
    UILineBreakMode mode = label.lineBreakMode; 

    CGFloat labelWidth  = label.frame.size.width; 
    CGFloat labelHeight = label.frame.size.height; 
    CGSize sizeConstraint = CGSizeMake(labelWidth, CGFLOAT_MAX); 

    if ([string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) 
    { 
     NSString *adjustedString; 

     for (NSUInteger i = 1; i < [string length]; i++) 
     { 
      adjustedString = [string substringToIndex:i]; 

      if ([adjustedString sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) 
       return i - 1; 
     } 
    } 

    return [string length]; 
} 

Usted probablemente podría hacer esto más eficiente si, por ejemplo, verificaras si el modo de salto de palabra, salta al siguiente separador de palabras y luego llama al sizeWithFont, pero para pequeños UILabel s esto podría ser suficiente. Si quería aprovechar la lógica word-wrap para reducir al mínimo el número de veces que se llama a sizeWithFont, es posible que tenga algo como:

- (NSUInteger)fitString:(NSString *)string intoLabel:(UILabel *)label 
{ 
    UIFont *font   = label.font; 
    UILineBreakMode mode = label.lineBreakMode; 

    CGFloat labelWidth  = label.frame.size.width; 
    CGFloat labelHeight = label.frame.size.height; 
    CGSize sizeConstraint = CGSizeMake(labelWidth, CGFLOAT_MAX); 

    if ([string sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height > labelHeight) 
    { 
     NSUInteger index = 0; 
     NSUInteger prev; 
     NSCharacterSet *characterSet = [NSCharacterSet whitespaceAndNewlineCharacterSet]; 

     do 
     { 
      prev = index; 
      if (mode == UILineBreakModeCharacterWrap) 
       index++; 
      else 
       index = [string rangeOfCharacterFromSet:characterSet options:0 range:NSMakeRange(index + 1, [string length] - index - 1)].location; 
     } 
     while (index != NSNotFound && index < [string length] && [[string substringToIndex:index] sizeWithFont:font constrainedToSize:sizeConstraint lineBreakMode:mode].height <= labelHeight); 

     return prev; 
    } 

    return [string length]; 
} 

Tal vez el conjunto de caracteres utilizado aquí no es del todo bien (en caso de que incluir guiones, por ejemplo), pero probablemente sea bastante cercano y mucho más eficiente que hacer personaje por personaje, si no necesita hacer eso.

+0

¡Realmente gracias! –

+3

Este método ahora está en desuso, por lo que puede usar - (CGRect) boundingRectWithSize: (CGSize) opciones de tamaño: (NSStringDrawingOptions) contexto de opciones: (NSStringDrawingContext *) NS_AVAILABLE_IOS (6_0); en su lugar – Will

Cuestiones relacionadas