Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emoji renders incorrectly #82

Closed
tonymillion opened this issue Apr 13, 2012 · 19 comments
Closed

Emoji renders incorrectly #82

tonymillion opened this issue Apr 13, 2012 · 19 comments

Comments

@tonymillion
Copy link

Hi, I've been trying to replace UILabel with TTTAttributedLabel so I can lankily URLS, I came across a weird edge-case involving emoji, I don't know if its indicative of a "larger problem", but might be worth looking at.

background: This is a tableview in which the cells contains a UILabel, in

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

I calculate the height of the cell using the following:


                CGSize requiredSize = [text sizeWithFont:[UIFont fontWithName:@"American Typewriter" size:17]
                                       constrainedToSize:CGSizeMake(POST_WIDTH, CGFLOAT_MAX)
                                           lineBreakMode:UILineBreakModeWordWrap];

                return 30 + requiredSize.height + 10;

(30 for the header + the required label height + 10 for the footer).

This works fine for UILabel and TTTAttributedLabel as long as they're displaying "plain text". As soon as the text contains an emoji the UILabel continues to render correctly, however the TTAttributedLabel no longer renders anything! (i.e. the TTTAttributedLabel view is completely "empty" as if nothing was rendered into it).

If I change the +10 to +16 (i.e to add an extra 6 pixels to the label) the text then renders properly, except with extra whitespace.

Initial investigation shows that the text is being rendered differently (some screenshots):

UILabel:
uilabel

TTTAttributedLabel
uilabel

Notice how the Emoji is rendered vertically centred on the UILabel, but baseline on the TTTAttributedLabel?

I don't have a solution just yet - I'll report back any findings but I wanted to log the issue incase you already know how to fix it!

@mooshee
Copy link

mooshee commented Apr 18, 2012

I'm having the same issue. It seems that the frame is drawn incorrectly. You can witness this by attempting to set the label's height using sizeWithFont. A single line of text will not show up, because the frame is too small. However, in a UILabel, it fits the text perfectly.

@mooshee
Copy link

mooshee commented Apr 27, 2012

After much headache, I found a better approach for calculating the correct height for a label with attributed text. So you can get rid of you hardcoded padding so it renders. I haven't had much luck correcting the vertical alignment of the emoji though.

Hope it helps!

- (CGFloat)heightWithMutableAttributedString:(NSMutableAttributedString*)mutableAttString ForWidth:(CGFloat)width
{
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString( (CFMutableAttributedStringRef) mutableAttString); 
    CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), NULL);
    CFRelease(framesetter);
    return suggestedSize.height;
}

Probably better served as a NSMutableAttributedString category.

@johndpope
Copy link

thanks for the heightWithMutableAttributedString method Mooshee.

@bogardon
Copy link

Has anyone figured this out yet? I'm using HelveticaNeue with pt size 11 and i too have the problem where multiline text with emojis do not draw correctly.

http://stackoverflow.com/questions/3374591/ctframesettersuggestframesizewithconstraints-sometimes-returns-incorrect-size

this thread suggests that setting the leading for paragraph style is the solution. but i believe he is mistaken...

It seems that emojis will increase its line height and hence may force its line or other lines below to not be rendered at all...

@bogardon
Copy link

bogardon commented Aug 3, 2012

In the end my really ugly hack involved adding +1 to every height calculation using CTFramesetters...

@SRandazzo
Copy link

@mooshee fix worked for me! thanks

@ghost
Copy link

ghost commented Aug 24, 2012

I think you need to use sizeThatFits: method, instead of UILabel's sizeWithFont. Although sizeThatFits sometimes doesn't calculate the correct height of the text including non-ASCII characters. =(

@jonasman
Copy link

jonasman commented Dec 5, 2012

Same problem here, What was the best fix so far?
In my case i needed to add 5 more pixels for the emoji to work..

@mattt mattt closed this as completed Dec 14, 2012
@jonasman
Copy link

The fix is not so pretty, if you use the TTTLabel in a tableView you need to calculate the size before showing the cell (heightforCell), in this case you need to create a dummy TTTLabel just for calculating the height of the cell!

Isn't there any other solution? like calculating the NSAttributed string height (the problem is that we need to set up all the attributes that TTTLabel applies)?

@Ani111
Copy link

Ani111 commented Jan 28, 2013

i have a problem with TTTAttributLabel multiline link, it doesnt work, please help me, is it possible to make multiline link of this kind?

@rnaud
Copy link

rnaud commented Feb 4, 2013

Sorry to bump but we have the same problem over here. It seems the Emoji actually change the line height of the line.

@ay8s
Copy link
Contributor

ay8s commented Feb 6, 2013

Looks like emoji is displaying now in 1.5.1, which it didn't do previously for me. However as @rnaud mentioned the lineheight is changed when Emoji is included.

iOS-Simulator-Screen-shot-6-Feb-2013-14 03 09

@sjapps
Copy link

sjapps commented Feb 25, 2014

any updates on this?

@iwasrobbed
Copy link

@sjapps The best option is to use the sizeThatFitsAttributedString:withConstraints:limitedToNumberOfLines: method built into TTTAttributedLabel. This will take into account the line height differences and give you a more accurate height than using iOS 7's textRectForBounds:

@sergisolanellas
Copy link

I create this function, to set height correct with uilabel with emojis.

Remember to include : CoreText/CoreText.h

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

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

    // Change the font type
    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; // I add 10 px

}

@jmmoser
Copy link

jmmoser commented Jun 3, 2014

Depending on the setup this may be all you need to fix this issue:

myLabel.clipsToBounds = NO;

@troypayne
Copy link

+1 same issue

@ghost
Copy link

ghost commented Sep 30, 2014

many thanks @mooshee , I have followed your code, and it works well

@jpsison-io
Copy link

Just add textinset

chatTextLabel.textInsets = UIEdgeInsetsMake(1.5, 0, 1.5, 0)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests