2013-10-23 15 views
17

In einem UITableView, das eine lange Liste von Chat-Konversationen anzeigen muss, die oft Emojis enthalten, tritt ein Größenberechnungsfehler auf.Emojis mit obj-c sizeWithFont Mathe

Mein Problem ist, dass, wenn eine Zeichenfolge genau die richtige Länge ist, und ich sizeWithFont verwende, bekomme ich bei meiner ersten Messung mit sizewithfont eine falsche Länge der Zeichenfolge, was einen "Zeilenumbruch" verursacht.

Ich nehme an, dass es ist, weil die Zeichenfolge ":-)" breiter als das eigentliche Smiley-Symbol ist.

Der Beweis ist hier zu sehen:

Using <code>SizeWithFont</code>

Jetzt bei einigen anderen Stapel, über, einige behaupten, dass sizeWithFont nur für die Zeichenfolge ausmachen werden, nicht die Emoji, die für mich nicht macht Sinn, da es richtig ist "irgendwann" ...

Aber sie schlagen vor, mit sizeToFit stattdessen, also habe ich beschlossen, es auszuprobieren.

Using SizeToFit

Bam, das gleiche Resultat.

Kann jemand dem entgegenwirken? Gibt es eine boolean, um zu überprüfen, ob "Label fertig ist Emoji-verarbeitet", so kann ich diesen Anruf überspringen?

Das Ausführen der gleichen Zeile zweimal tut nichts, es scheint, dass die Ansicht gezeichnet werden muss, bevor sizeWithFont seinen Fehler erkennt.

Die angezeigte Spalte wird in einem Segment - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath in einer benutzerdefinierten Zelle ausgeführt. Ich kann den Fehler auch auf einer vollkommen regulären UITableViewCell replizieren, so scheint es nicht zu sein.

+0

Skalieren Sie ein Etikett oder die Zelle selbst? Wenn nur das Etikett dimensioniert wird, denke ich, dass ich das automatische Layout verwenden werde, um all die Magie zu nutzen. Programmatisch berechnen Sie die Größe des Etiketts ist fehleranfällig. – zetachang

+0

Ich habe festgestellt, dass dies gute Messwerte liefert, aber ich habe Emojis nicht versucht. - [UILabel textRectForBounds: limitedToNumberOfLines:] –

+3

ab iOS 7 'sizeWithFont: constrainedToSize: lineBreakMode' ist veraltet und wird durch' boundingRectWithSize ersetzt: options: attributes: context: ' – aug2uag

Antwort

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

Du hast gerade meinen Tag gemacht, ich kämpfe seit Stunden damit und Ihre Lösung wirkt wie ein Zauber ... Hände nach unten! – sachadso

+1

Hallo @SergiSolanellas, du bist toll :). Ich habe 1 Tag für Lösung für diese Bibliothek [STTweetLabel] https://github.com/SebastienThiebaud/STTweetLabel verbracht und Ihre Antwort ist sehr hilfreich für mich .. Vielen Dank. –

+0

Hallo @SergiSolanellas. Ich brauche deine Hilfe. Wenn in meinem Text so viele neue Zeile ('\ n') Zeichen enthalten ist und kein Emoji im Text zu dieser Zeit gibt mir diese Funktion falsche Höhe. Irgendeine Lösung dafür ??? –

6

Danke @SergiSolanellas! Hier ist eine Version, die einen attributedString verwendet, wodurch die Methode verkürzt wird, weil der Text und die Schriftart bereits festgelegt sind.

// 
// 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; 
}