Is it possible to use the autoshrink property in conjunction on multiple lines on a UILabel
? for example, the large text size possible on 2 available lines.
Here's the category solution updated to iOS 7 based off of itecedor's updates for iOS 6.
Header file:
#import <UIKit/UIKit.h>
@interface UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit;
@end
And the implementation file:
@implementation UILabel (MultiLineAutoSize)
- (void)adjustFontSizeToFit {
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor * self.font.pointSize; maxSize -= 1.f)
{
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGRect textRect = [self.text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:font}
context:nil];
CGSize labelSize = textRect.size;
if(labelSize.height <= size.height)
{
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout]; }
@end
i liked DaGaMs's answer, but in using labels like in UITableViewCells that could be returned of dequeueReusableCell:, the regular font size would continue to shrink even as the original font size was still desired for some tableView cells that had less text and could take advantage of the original label's original font size.
so, i starting with DaGaMs's category as a jumping off point, i created a separate class rather than a separate category, and i make sure my UILabels in my storyboard make use of this new class:
#import "MultiLineAutoShrinkLabel.h"
@interface MultiLineAutoShrinkLabel ()
@property (readonly, nonatomic) UIFont* originalFont;
@end
@implementation MultiLineAutoShrinkLabel
@synthesize originalFont = _originalFont;
- (UIFont*)originalFont { return _originalFont ? _originalFont : (_originalFont = self.font); }
- (void)quoteAutoshrinkUnquote
{
UIFont* font = self.originalFont;
CGSize frameSize = self.frame.size;
CGFloat testFontSize = _originalFont.pointSize;
for (; testFontSize >= self.minimumFontSize; testFontSize -= 0.5)
{
CGSize constraintSize = CGSizeMake(frameSize.width, MAXFLOAT);
CGSize testFrameSize = [self.text sizeWithFont:(font = [font fontWithSize:testFontSize])
constrainedToSize:constraintSize
lineBreakMode:self.lineBreakMode];
// the ratio of testFontSize to original font-size sort of accounts for number of lines
if (testFrameSize.height <= frameSize.height * (testFontSize/_originalFont.pointSize))
break;
}
self.font = font;
[self setNeedsLayout];
}
@end
I've written a small category on UILabel based on "The Dude's" answer above to achieve this functionality.
https://gist.github.com/ayushn21/d87b835b2efc756e859f
The answer marked as the solution is hacky and imprecise. UILabel will handle it automatically if you set the following properties correctly:
numberOfLines
must be nonzero
adjustsFontSizeToFitWidth
must be YES
lineBreakMode
must not be NSLineBreakByCharWrapping
or NSLineBreakByWordWrapping
Thank you to DaGaMs for this solution.
I've updated it as follows:
1 - To work with iOS 6 (since both minimumFontSize and UILineBreakModeWordWrap are deprecated) 2 - To strip whitespace from the label's text, as it will cause the resizing to fail (you don't want to know how long it took me to find that bug)
-(void)adjustFontSizeToFit
{
self.text = [self.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
UIFont *font = self.font;
CGSize size = self.frame.size;
for (CGFloat maxSize = self.font.pointSize; maxSize >= self.minimumScaleFactor; maxSize -= 1.f)
{
font = [font fontWithSize:maxSize];
CGSize constraintSize = CGSizeMake(size.width, MAXFLOAT);
CGSize labelSize = [self.text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
if(labelSize.height <= size.height)
{
self.font = font;
[self setNeedsLayout];
break;
}
}
// set the font to the minimum size anyway
self.font = font;
[self setNeedsLayout];
}
For UIButton, just these lines are working for me:
self.centerBtn.titleLabel.numberOfLines = 2;
self.centerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
self.centerBtn.titleLabel.adjustsFontSizeToFitWidth = YES;