UILabel italic font

I am trying to solve this problem, since I have a lot of fonts in the application I'm working on, so the label size is calculated dynamically when the user changes the font.

The problem I am facing is that the UILabel is truncated at the end if the font is italic, as in the picture below:

UILabel clipping example

This is what I have tried so far:

  • Width calculation using CoreText and CGSize CTFramesetterSuggestFrameSizeWithConstraints ( CTFramesetterRef framesetter, CFRange stringRange, CFDictionaryRef frameAttributes, CGSize constraints, CFRange *fitRange );
  • width calculation using NSAttributedString and - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context
  • calculating width using NSString and - (CGSize)sizeWithAttributes:(NSDictionary<NSString *,id> *)attrs
  • using temp UITextView and sizeThatFits´ and fitToSize`

Since there are a lot of fonts in the application, I need to set the label width dynamically, so subclassing UILabel and adding a few points on drawFrameInRect do not work.

Here is a sample code on Github .

Any help / advice is appreciated.

+6
source share
7 answers

Even I don’t have time to check it, I’m sure that the problem is that the size of the label is calculated from the advances. Promotion is the amount of movement from one character’s base point to the next. Usually for an italic font, the advance may be less than the boundaries. Therefore, adding advances will shorten the end of the layout.

those. Baskerville-Italic H :

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

Therefore, I believe that you need to add the difference between the prefix and the bounding box of the last character, if the text is perfect layout (no compression, etc.).

To get both values, you need to call some CT functions:

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

Typed in Safari.

Addition: you have the same problem on the left side: the transition to upper case L is 0 (the first character), but the bounding box has a negative x. Therefore, the left side is cut off. Add a place there too .. (Which is much simpler).

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

And update the width and height of the shortcut from adjustSize.Hope it works

+1
source

I would use Auto Layout on your buttons and on your shortcut to always keep it in the center based on the font size that you choose for your label.

Then remove all this code in the updateLabel method. I'm not sure why you are using UITextview and bring this jazz to the image. If you click on your shortcut in your storyboard and check the attribute inspector and find "Autoshrink", it should be set to "Minimum Font Size" NOT "Fixed Font Size".

Then I would use NSAttributedString on your shortcut to resize it and font based on which button is clicked.

0
source

I downloaded your GitHub project, and it seems that UILabel and UITextField definitely calculate text borders differently. So, I first tried to assign the resulting size from sizeToFit to UITextField to UILabel size. However, this approach breaks down for the Strato font.

After trying some other approaches that failed, I remembered that italic fonts have more or less the same angle. A italic version of a font usually increases the width of the bounding box by the same proportion as the original width.

Update:

Therefore, you should be able to infer the width of the italic line from its width and font size. I tried this approach in your project and it works for all the fonts you specified. I used the following formula:

CGRect calculateRect = [attribatedString boundingRectWithSize: CGSizeMake options (CGFLOAT_MAX, CGFLOAT_MAX): (NSStringDrawingUsesLineFragmentOrigin): nil];

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

Since this depends on the added width due to italics, highlighting in bold fonts such as Strata will have a greater effect on the width.

Obviously, if and when the text API is complemented by reliable calculations for the width of the text, you can accept it. However, the workaround I presented may still be the best choice if you want backward compatibility.

I hope this helps!

0
source

You will achieve much better results using NSStringDrawingUsesDeviceMetrics in boundingRectWithSize:options:context:

0
source

1: Set the text to your shortcut with the current font selected.

2: use this method

 - (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: Then install

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

Hope this works for you.

0
source

try it

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

All Articles