2012-06-22 6 views
5

Ho 4 linee UILabel con struttura esatta e font.Come sapere se NSString si inserisce in UILabel o meno e indice dell'ultima stringa che si adatta?

ho bisogno di sapere se questa stringa si inserisce l'etichetta e che cosa è l'indice dell'ultimo carattere che si adatta.

+3

Questa domanda dovrebbe essere d'aiuto: http://stackoverflow.com/questions/6422742/how-to-know-the-length-of-nsstring-that-fits-a-uilabel-with-fixed-size –

+0

Avevo già guardato prima ma non ha aiutato –

+0

la risposta @Cupcake pubblicata qui dovrebbe aiutarti –

risposta

8

Il kernel della risposta è nel post di riferimento di Cupcake. Comunque, è possibile utilizzare sizeWithFont:constrainedToSize:lineBreakMode: per capire quale sia la dimensione di un frame sarebbe con un carattere particolare in un'etichetta di una data larghezza data una parola specifica incarto, ad esempio

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

Set sizeConstraint essere la stessa larghezza della vostra etichetta, ma impostare l'altezza per essere più grande. Se lo size.height risultante è più grande di UILabel, la stringa è troppo lunga. In teoria, è possibile rimuovere l'ultimo carattere/parola e riprovare e ripetere finché non si adatta.

Se pensate che le stringhe potrebbero essere molto lunghe, potreste voler andare dall'altra parte, iniziare con una piccola parte della stringa e continuare ad aggiungere caratteri finché non è troppo grande, e quindi conoscete l'ultimo carattere.

Ad ogni modo, questo calcolo iterativo della dimensione può essere abbastanza un'operazione dispendiosa cpu, quindi fate attenzione.

Aggiornamento:

Ecco un algoritmo che restituisce la lunghezza della NSString che può andare bene nella UILabel in questione utilizzando il font di default (ma ignorando dimensione minima del font):

- (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]; 
} 

È potrebbe probabilmente renderlo più efficiente se, ad esempio, verifichi la modalità di interruzione delle parole, saltando al separatore di parole successivo e chiamando sizeWithFont, ma per i piccoli UILabel s ciò potrebbe essere sufficiente. Se si voleva sfruttare la logica word-wrap per ridurre al minimo il numero di volte che si chiama sizeWithFont, si potrebbe avere qualcosa di simile:

- (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]; 
} 

Forse il set di caratteri utilizzato qui non è abbastanza di destra (dovrebbe includere trattini, per esempio), ma probabilmente è abbastanza vicino e molto più efficiente rispetto al carattere per carattere, se non è necessario farlo.

+0

Davvero grazie! –

+3

Questo metodo è ora deprecato, quindi è possibile utilizzare - (CGRect) boundingRectWithSize: (CGSize) opzioni di dimensione: (NSStringDrawingOptions) contesto delle opzioni: (NSStringDrawingContext *) contesto NS_AVAILABLE_IOS (6_0); invece – Will

Problemi correlati