iOS: sizeWithFont: for custom font - ios

I've been plugging away and I need to use the sizeWithFont: method to properly line up my layout, but it doesn't seem to work with custom fonts. Is there a way to get it to work, or maybe another method I can use?
I'm pretty stumped on this. Any help is appreciated.

sizeWithFont should definitely work, but if it's giving you a problem then there is a workaround. You can put the text in a UITextView, add it to your layout, and then retrieve the actual text size and adjust accordingly. Here's some sample code from one of my projects:
// Put in the title in
self.titleView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 195, 195)];
self.titleView.font = [UIFont fontWithName:#"Bliss Pro" size:20.0];
[self addSubview:self.titleView];
self.titleView.text = #"Add your text here";
// Now get the actual size of the text and resize the title view's frame
CGRect frame = self.titleView.frame;
frame.size.height = self.titleView.contentSize.height;
self.titleView.frame = frame;
It's a bit hackish, but it certainly works.

#define kFontSize 14.0 //modify your font size
CGSize size = [yourView sizeWithFont:[UIFont boldSystemFontOfSize:kFontSize]];

Related

iOS API - sizeThatFits: does not work

UPDATE:
Sorry I didn't describe it enough and incorrectly before.
I did some code like this:
UIView *view = [[UIView alloc] initWithFrame:someFrame];
CGSize size = [view sizeThatFits:CGSizeMake(100, 100)];
But when I observe size, it got nothing: {0, 0}.
Do I use it wrong?
Even I passed in an initial frame to my view, the size still returned nothing.
I searched some posts and someone said UILabel may also gets affected.
Your view does't contain any content and it does't have any intristic content size, so it will have zero size.
Try these and you will see that it works:
UILabel *label [UILabel new];
label.text = #"test test test test";
CGSize size = [label sizeThatFits:CGSizeMake(20, CGFLOAT_MAX)];
As a #Konstantin said:
Your view does't contain any content and it does't have any inartistic
content size
So try to use this code
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)];
CGSize size = view.size;
Check the description of sizeThatFits, it states,
Asks the view to calculate and return the size that best fits the
specified size. A new size that fits the receiver’s subviews.
So, your view should have some subview or content otherwise it will return 0,0.

How can I trim the height of UILabel to perfectly fit the text without ever changing font size?

Here is my UILabel (defined by what is in the yellow):
Here is after I add [shortDescriptionLabel sizeToFit]; to end of my code:
Here is a second example (to show that the font size is actually getting changed after sizeToFit:
Here is after I add [shortDescriptionLabel sizeToFit]; to end of my code (it is clear that the font size reverted back to size 30.0):
I would like to trim the excess height (above and below carrots). How can I do this? Here is my current code:
shortDescriptionLabel = [[UILabel alloc]initWithFrame:CGRectMake(itemImageView.frame.origin.x+itemImageView.frame.size.width+10, 20, self.tableView.frame.size.width-itemImageView.frame.origin.x- itemImageView.frame.size.width-20-20, tableViewCellHeight/2)];
shortDescriptionLabel.text = itemObject.shortDescription;
shortDescriptionLabel.font = [UIFont boldSystemFontOfSize:30];
shortDescriptionLabel.textAlignment = NSTextAlignmentCenter;
shortDescriptionLabel.adjustsFontSizeToFitWidth = YES;
shortDescriptionLabel.numberOfLines = 0;
shortDescriptionLabel.minimumScaleFactor = 0;
[shortDescriptionLabel setBackgroundColor:[UIColor yellowColor]];
CGFloat fontSize = shortDescriptionLabel.font.pointSize;
NSLog(#"fontSize = %f", fontSize);
Keep in mind that the last NSLog will always display 30.0 (the font size set earlier) even if the displayed font size is obviously smaller than 30.0.
Please help. There seems to be a lot about this online but I can't seem to get anything to work.
Yoh can use sizeToFit but if you want to trim the height and keep the width you can add a height constraint equal to the used UIFont's lineHeight.
AutoLayout
1-Properly Add its Leading,Trailing,Top and bottom Constraints and Write this line of code will do
[label setPreferredMaxLayoutWidth:300.0];
Non AutoLayout
-(CGSize)m_GetHeight:(NSString*)text
{
CGSize constraintSize=[text sizeWithFont:[UIFont fontWithName:#"Arial" size:15.] constrainedToSize:CGSizeMake(182, 2000) lineBreakMode:NSLineBreakByWordWrapping];
return constraintSize;
}

NSString sizing does not account for Greek breathing marks

I've got an app that displays Greek text. I use the Cardo font for good display. In working on an AppleWatch extension and app, it was pointed out to me that some of the special characters are being cut off. This is how some example text should look (screenshot from an iPhone simulator):
Here is the same text on the Watch simulator:
Note that the fancy accent character (to be specific, a breathing mark with a circumflex accent) on the second character of the first word is cut off. I tried setting the label's frame on the phone using some NSString measuring code like this:
UILabel *label = [[UILabel alloc]init];
label.font = [UIFont fontWithName:#"Cardo" size:16];
[self.view addSubview:label];
label.text = #"οὗτος ἦλθεν εἰς μαρτυρίαν ἵνα μαρτυρήσῃ περὶ τοῦ φωτός, ἵνα πάντες πιστεύσωσιν δι᾽ αὐτοῦ.";
label.numberOfLines = 0;
label.lineBreakMode = NSLineBreakByWordWrapping;
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc]init];
style.lineBreakMode = NSLineBreakByWordWrapping;
CGRect rect = [label.text boundingRectWithSize:self.view.bounds.size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName: label.font,
NSParagraphStyleAttributeName: style} context:nil];
label.frame = CGRectMake(5, 100, ceilf(rect.size.width), ceilf(rect.size.height));
label.layer.borderWidth = 1; //for clarity
label.layer.borderColor = [UIColor blackColor].CGColor;
The result looks like this (the border is drawn for clarity's sake):
Interestingly, if I use the system font instead of Cardo, the extra symbols display correctly:
So, my question: What causes the NSString sizing to cut off the extra marks? Is there some option I can pass to the sizing method to correct this? Or better yet, is there some option I can set on the WKInterfaceLabel in the Watch app to get it to render correctly?
I don't know if this will fix it or not, but this will give you more to look into. I ran into an issue with a font using "Lower Case" numbers, which is a typography style for tabular numbers. I was able to create a variation of the font using a UIFontDescription that forced all numbers to be upper case. In your case the font's ascenders go over the top of the font's capHeight. There are a bunch of options for creating a font using a font descriptor and one of them may help. Here is how I created the upper case number font.
_font = [UIFont fontWithName:_fontName size:size];
NSArray* featureSettings = #[
#{
UIFontFeatureTypeIdentifierKey: #(kNumberCaseType),
UIFontFeatureSelectorIdentifierKey: #(kUpperCaseNumbersSelector)
}];
UIFontDescriptor* originalDescriptor = [_font fontDescriptor];
UIFontDescriptor* newDescriptor = [originalDescriptor fontDescriptorByAddingAttributes: #{UIFontDescriptorFeatureSettingsAttribute: featureSettings }];
_font = [UIFont fontWithDescriptor: newDescriptor size: size];
Specifically check out the kVerticalPositionType.
I actually ran into a case in my iOS app where the font ascenders where going over the capHeight from the baseline up and my attributed string was getting cut off. Since I was in quartz drawing code I just use the difference of the font's lineHeight with its ascender and padded the top. Unfortunately that is not an option on the Apple Watch.
I suspect the problem is in the font itself, with the ascenders being set too tightly for proper display.
I would first try setting the UILabel's text inset by making a subclass of UILabel and overriding drawTextInRect:
- (void)drawTextInRect:(CGRect)rect {
UIEdgeInsets insets = {5, 0, 0, 0};
[super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
If you have tried increasing the text inset to accommodate the font and it has not worked, take a look at Custom installed font not displayed correctly in UILabel

Text Alignment issue when I set the custom font

When I set the custom font for the segmented control then it changes the vertical text alignment. I am using below code to set the font .
// I dont think these lines are creating any issue but just wanted to paste all the code
self.segmentType.layer.borderColor = navigationTintColor.CGColor;
self.segmentType.layer.cornerRadius = 0.0;
self.segmentType.layer.borderWidth = 1.5;
// These are the lines that are changing the text alignment
UIFont *font = [UIFont fontWithName:ftHelveticaNeueLTPro_Th size:13.5];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font
forKey:UITextAttributeFont];
[self.segmentType setTitleTextAttributes:attributes
forState:UIControlStateNormal];
Here is the screenshot of whats is happening . If you observer, the text is not vertically centre aligned .
Please help me . Thank you in advance !!
The below code suggested by #Emmanuel works perfectly fine. You can change the vertical offset to align the text vertically at the center .
[self.segmentType setContentPositionAdjustment:UIOffsetMake(0, 2) forSegmentType:UISegmentedControlSegmentAny barMetrics:UIBarMetricsDefault];
Can you please try it using custom UILabel on custom view on it. Change & modify frame value of either titleLabel or customSegmentView as per convenience on actual view. And add this whole view as subview on your segmented control.
UIView *customSegmentView = [[UIView alloc] init];
UILabel *segmentTitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 7.0f,180.0f,22.6f)];
segmentTitleLabel.text = #"your-text";
segmentTitleLabel.backgroundColor = [UIColor clearColor];
segmentTitleLabel.textAlignment = UITextAlignmentCenter;
segmentTitleLabel.font = [UIFont fontWithName:#"ftHelveticaNeueLTPro_Th" size:13.5f];
customSegmentView.frame = CGRectMake(60, 20, 180, 35);
[customSegmentView addSubview:segmentTitleLabel];
[self.segmentType setTitleView:customSegmentView];
Hope that will work for your issue. Please check and let me know if we have to go with another solution.
In InterfaceBuilder on XCode 6 there is a Content Offset control for the segments, which affects the baseline of the text. I had this problem because my Content Offset was 2 in the Y dimension instead of 0.

Adding additional space to UILabel to insert image

I have an issue with adding image in the end of the text of the UILabel. How can I detect the size of the text in the label, then add additional space and insert image into it?
i write a little code for this:
-(void) labelSizeGetter
{
UILabel * mylabel=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
float heigth=25.0;//max height value of label.
NSString *yourString = #"My great text";
mylabel.font =[UIFont fontWithName:#"Helvetica-Bold" size:12];
[mylabel setText:yourString];
CGSize s = [mylabel.text sizeWithFont:[UIFont systemFontOfSize:12]
constrainedToSize:CGSizeMake(MAXFLOAT,heigth)
lineBreakMode:NSLineBreakByWordWrapping];
// s is a size for text of label. just add 10 pix to width to make it more beautiful.
NSLog(#"%#", NSStringFromCGSize(s));
mylabel.frame=CGRectMake(0, 0, s.width+10, s.height);
[self.view addSubview:mylabel];
UIView * myimage=[[UIView alloc] initWithFrame:CGRectMake(mylabel.frame.origin.x+mylabel.frame.size.width , mylabel.frame.origin.y, 30, 30)];//create your images frame according to frame of your label
myimage.backgroundColor =[UIColor colorWithPatternImage:[UIImage imageNamed:#"arti.png"]];
[self.view addSubview:myimage];
}
i hope it helps
Best Way is take one UIView.
And Add Both UILabel And UIImageView on This UIView (give Fram as per your Requirement).
And This UIView to your MainView of UIViewController.
If you dont want to use a UIView. Why not check the length of the string in the label. then add some additional space for your image using frame. [UILabel.text length] returns the length.
Create some container UIView if you need or just use superview
Put there UILabel and UIImageView
Calculate a size of the text using [NSString sizeWithFont:] or similar sizeWith... method
Calculate position of your UIImageView according to a size of the text
Here is a code snippet which gives you size adjustable for specific font and specific font size. Accordingly you can set frame for your label and then image view as well.
- (CGSize)getSizeFromText:(NSString*)text {
CGSize constrainedSize;
constrainedSize.width = give maximum allowable width limit;
constrainedSize.height = MAXFLOAT;
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:fontSize] constrainedToSize:constrainedSize lineBreakMode: UILineBreakModeWordWrap];
return size;
}
Hope this would help you to solve your problem.
There is a category on NSString that returns the size of a string when rendered with a given font. There are several methods, the most complete on being - (CGSize)sizeWithFont:(UIFont *)font minFontSize:(CGFloat)minFontSize actualFontSize:(CGFloat *)actualFontSize forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode (see Apple Docs).
With that information you might be able to achieve what you want to do.

Resources