2013-10-23 20 views
17

In un UITableView che deve visualizzare un lungo elenco di conversazioni chatlike, che spesso contengono emoji, si verifica un errore di calcolo delle dimensioni.Emojis scherza con la dimensione di obj-cWithFont matematica

Il mio problema è che, se una stringa è della lunghezza giusta e io uso sizeWithFont, nella prima misura utilizzando sizewithfont ottengo una lunghezza errata della stringa, causando un "interruzione di riga".

Suppongo che sia perché la stringa ":-)" è più ampia dell'effettiva icona di emoticon.

La prova può essere visto qui:

Using <code>SizeWithFont</code>

Ora, oltre ad alcuni altri stack, alcuni sostengono che sizeWithFont rappresenteranno solo per la stringa, non l'Emoji, che per me non fa senso, dal momento che va bene "alla fine" ...

Ma loro propongono invece di usare sizeToFit, quindi ho deciso di provarlo.

Using SizeToFit

Bam, stesso risultato.

Qualcuno sa come contrastarlo? Esiste un boolean per verificare se "L'etichetta è terminata con l'elaborazione delle emoji", quindi posso saltare quella chiamata?

L'esecuzione della stessa linea due volte non fa nulla, sembra che la vista debba essere disegnata, prima che sizeWithFont realizzi il suo errore.

La colonna visualizzata viene eseguita in un segmento - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, su una cella personalizzata. Posso anche replicare l'errore su una UITableViewCell perfettamente regolare, in modo che non sembri esserlo.

+0

Si sta dimensionando un'etichetta o la cella stessa? Se solo l'etichetta sta dimensionando, penso che userò il layout automatico per fare tutta la magia. Calcola in modo programmatico che la dimensione dell'etichetta sia soggetta a errori. – zetachang

+0

Ho trovato che questo restituisce buone misurazioni, ma non ho provato emoji. - [UILabel textRectForBounds: limitedToNumberOfLines:] –

+3

da iOS 7 'sizeWithFont: constrainedToSize: lineBreakMode' è deprecato e sostituito con' boundingRectWithSize: options: attributes: context: ' – aug2uag

risposta

13
- (CGFloat)heightStringWithEmojis:(NSString*)str fontType:(UIFont *)uiFont ForWidth:(CGFloat)width { 

// Get text 
CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); 
CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef) str); 
CFIndex stringLength = CFStringGetLength((CFStringRef) attrString); 

// Change font 
CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef) uiFont.fontName, uiFont.pointSize, NULL); 
CFAttributedStringSetAttribute(attrString, CFRangeMake(0, stringLength), kCTFontAttributeName, ctFont); 

// Calc the size 
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); 
CFRange fitRange; 
CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange); 

CFRelease(ctFont); 
CFRelease(framesetter); 
CFRelease(attrString); 

return frameSize.height + 10; 

} 
+0

Hai appena fatto la mia giornata, ho lottato per ore e la tua soluzione funziona come un incantesimo ... giù di mano! – sachadso

+1

Ciao @SergiSolanellas, sei fantastico :). Ho trascorso 1 giorno per ottenere una soluzione per questa libreria [STTweetLabel] https://github.com/SebastienThiebaud/STTweetLabel e la tua risposta mi è molto utile .. Grazie mille. –

+0

Ciao @SergiSolanellas. Ho bisogno del tuo aiuto. Quando nel mio testo ci sono così tante nuove righe ('\ n'), il carattere è contenuto e nessuna emoji nel testo in quel momento questa funzione mi dà un'altezza sbagliata. Qualche soluzione per quello ??? –

6

Grazie @SergiSolanellas! Ecco una versione che accetta un attributo String, abbrevia il metodo perché il testo e il carattere sono già impostati.

// 
// Given an attributed string that may have emoji characters and the width of 
// the display area, return the required display height. 
// 
- (CGFloat)heightForAttributedStringWithEmojis:(NSAttributedString *)attributedString forWidth:(CGFloat)width { 
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString); 
    CFRange fitRange; 
    CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange); 

    CFRelease(framesetter); 

    return frameSize.height; 
}