2015-11-29 24 views
6

Sto cercando di risolvere questo problema, come nell'applicazione in cui sto lavorando Ho molti font, quindi la dimensione dell'etichetta viene calcolata dinamicamente quando l'utente cambia carattere.UILabel carattere corsivo ritaglio

Il problema che ho è che UILabel viene agganciato alla fine se di carattere è in corsivo, come nella foto sotto:

UILabel clipping example

Questo è quello che ho provato finora:

  • calcolo della larghezza con l'aiuto di CoreText e CGSize CTFramesetterSuggestFrameSizeWithConstraints (CTFramesetterRef framesetter, CFRange stringRange, CFDictionaryRef frameAttributes, CGSize constraints, CFRange *fitRange);
  • calcolo della larghezza con l'aiuto di NSAttributoString e - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context
  • calcolo della larghezza con l'aiuto di NSString e - (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs
  • utilizzando Temp UITextView e sizeThatFits´ and fitToSize`

Come c'è un sacco di tipi di carattere in applicazione ho bisogno di impostare la larghezza di etichetta in modo dinamico, così sottoclassi di UILabel e l'aggiunta di alcuni punti in più su drawFrameInRect non funziona.

Ecco il codice di esempio Github.

Qualsiasi aiuto/consiglio è apprezzato.

+1

Vi siete esplorato questo: [la visualizzazione label] .clipsToBounds = NO; –

+0

Si dovrebbe assolutamente guardare nel caricamento automatico. –

+0

Ricordo di aver riscontrato questo problema da iOS 5 con il corsivo. Soprattutto quando si utilizza l'allineamento destro. Lo stavo risolvendo aggiungendo uno spazio alla fine del testo. È una soluzione stupida ma funziona. – Sulthan

risposta

0

Anche se non ho il tempo di testarlo, sono abbastanza sicuro che il problema è che la dimensione dell'etichetta viene calcolata dagli anticipi. L'anticipo è la quantità di movimento dal punto base di un personaggio a quello successivo. In genere per un carattere corsivo l'anticipo può essere più piccolo dei limiti. Quindi aggiungere gli anticipi taglierà la fine del layout.

I.e. Baskerville-italica H:

(lldb) p bounds[0].size 
(CGSize) $6 = (width=33.53515625, height=26.484375) 
(lldb) p advances[0] 
(CGSize) $7 = (width=30, height=0) 

Quindi penso che si deve aggiungere la differenza fra anticipo e rettangolo di selezione dell'ultimo carattere, se il testo è di layout in modo ideale (nessuna compressione e così via).

Per ottenere entrambi i valori, dovete chiamare alcune funzioni CT:

// What you probably have 
CTFontRef font = …; 
CFStringRef string = …; 
CFAAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes); 

// Get the character and glyph 
CFIndex count = CFStringGetLength(string); // The length of the string 
UniChar character; 
CFStringGetCharacters(string, CFMakeRange(count-1, 1), &character); 
CGGlyph glyph; 
CTStringGetGlyphsForCharacters(font, &character, &glyph,1 ); 

// Get the advance 
CGSize advance; 
CTFontGetAdvancesForGlyphs(font, 0, &glyph, &advance, 1); 

// Get the bounds 
CGRect bounds; 
CTFontGetAdvancesForGlyphs(font, 0, &glyph, &bounds, 1); 

digitato in Safari.

Aggiunta: si ha lo stesso problema sul lato sinistro: l'avanzamento sulla lettera maiuscola L è 0 (il primo carattere), ma il riquadro di delimitazione ha una x negativa. Pertanto il lato sinistro è tagliato. Aggiungi spazio anche lì .. (Che cosa è più facile di gran lunga.)

0

Vorrei utilizzare il layout automatico sui pulsanti e sull'etichetta per mantenerlo sempre centrato in base alla dimensione del carattere scelto per l'etichetta.

Quindi, eliminare tutto il codice nel metodo updateLabel. Non sono sicuro del motivo per cui usi UITextview e porti quel jazz nella foto. Se fai clic sull'etichetta nello storyboard e controlla l'ispettore di attributi e trovi "Autoshrink", dovrebbe essere impostato su "Dimensione minima carattere" NON "Fixed Font Size".

Vorrei quindi utilizzare NSAttributedString sull'etichetta per modificare le dimensioni e il tipo di carattere in base a quale pulsante si fa clic.

+0

UITextView è solo per test, per vedere come funziona il calcolo. Se provi il mio esempio nella console di debug, puoi vedere diversi tipi di larghezze basate su approcci diversi e i loro calcoli. Questa è l'unica ragione per cui è lì. Non sono in grado di utilizzare il layout automatico su questo progetto, ma il posizionamento non è un problema. Grazie per l'aiuto. –

+0

La mia risposta è stata nella direzione in cui eri diretto? –

+0

Un po ', ma è così che sto facendo in questo momento senza successo. Dato che non sono in grado di utilizzare l'auto-caricamento, devo calcolarlo manualmente e in modo dinamico. –

0

Ho scaricato il progetto GitHub e sembra che UILabel e UITextField stiano sicuramente calcolando i limiti del testo in modo diverso. Quindi, per prima cosa ho provato ad assegnare la dimensione risultante da sizeToFit su UITextField alla dimensione di UILabel. Tuttavia, questo approccio si interrompe per il carattere Strato.

Dopo aver provato alcuni altri approcci che hanno fallito, mi sono ricordato che i caratteri in corsivo si trovano più o meno nella stessa angolazione. La versione in corsivo del font solitamente aumenterà la larghezza del riquadro di delimitazione della stessa proporzione alla larghezza originale.

Aggiornamento:

Pertanto, si dovrebbe essere in grado di ricavare la larghezza di una stringa in corsivo dalla sua larghezza e dimensione del carattere. Ho provato questo approccio nel tuo progetto e funziona per tutti i tipi di carattere che hai elencato.Ho usato la seguente formula:

CGRect calculatedRect = [attributedString boundingRectWithSize: CGSizeMake (CGFLOAT_MAX, CGFLOAT_MAX) opzioni: (NSStringDrawingUsesLineFragmentOrigin) contesto: nil];

calcolatoRect.size.width = calculateRize.size.width + (label.font.pointSize * 0.2);

Poiché questo dipende dalla larghezza aggiunta dovuta al corsivo, il corsivo in grassetto, come Strata, avrà un impatto maggiore sulla larghezza.

Ovviamente, se e quando l'API del testo è aumentata per includere calcoli affidabili per la larghezza del testo, sarà possibile adottarla. Tuttavia, la soluzione alternativa che ho presentato potrebbe essere ancora una scelta migliore, se si desidera avere la compatibilità con le versioni precedenti.

Spero che questo aiuti!

+0

Che non può funzionare. L'aumento della larghezza non dipende dalla larghezza dell'intera stringa ma solo dall'ultima lettera. – Sulthan

+0

@ Sulthan, questo è un buon punto - ho trascurato questo. Quindi dovrebbe essere una funzione della dimensione del carattere, invece della larghezza. Grazie, lo proverò e aggiornerò la mia risposta. – Sheamus

0

Otterrai risultati molto migliori utilizzando NSStringDrawingUsesDeviceMetrics in boundingRectWithSize:options:context:.

1
CGSize size = [label.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0f]}]; 
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height)); 

E aggiornare la larghezza del marchio e l'altezza da adjustedSize.Hope funziona

0

1: impostare il testo per l'etichetta con il vostro carattere corrente selezionato.

2: utilizzare questo metodo

- (CGSize)getSizeforController:(id)view 
{ 
    UILabel *tempView =(UILabel *)view; 
    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init]; 
    context.minimumScaleFactor = 0.8; 
    float height = tempView.frame.size.height; 
    CGSize size=[tempView.text boundingRectWithSize:CGSizeMake(2000, height)options:NSStringDrawingUsesLineFragmentOrigin attributes:@{ NSFontAttributeName : tempView.font}context:context].size; 
    return size; 
} 

3: Quindi impostare

CGSize newSize = [self.getSizeforController:self.lblYourLabel]; 
self.lblYourLabel.frame.size = newSize; 

Spero che questo funzionerà per voi.

0

Prova questo

CGSize lableWidth = CGSizeMake(300, CGFLOAT_MAX); 
CGSize requiredSize = [yourLabel sizeWithFont:[UIFont fontWithName:@"FontName" size:17] constrainedToSize:lableWidth lineBreakMode:NSLineBreakByWordWrapping]; 
int calculatedHeight = requiredSize.height;