Autoshrink on a UILabel with multiple lines

前端 未结 17 1958
醉梦人生
醉梦人生 2020-11-28 21:31

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.

相关标签:
17条回答
  • 2020-11-28 21:55

    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
    
    0 讨论(0)
  • 2020-11-28 21:56

    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
    
    0 讨论(0)
  • 2020-11-28 21:57

    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

    0 讨论(0)
  • 2020-11-28 22:00

    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

    0 讨论(0)
  • 2020-11-28 22:01

    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];
    }
    
    0 讨论(0)
  • 2020-11-28 22:05

    For UIButton, just these lines are working for me:

    self.centerBtn.titleLabel.numberOfLines = 2;
    self.centerBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
    self.centerBtn.titleLabel.adjustsFontSizeToFitWidth = YES;
    
    0 讨论(0)
提交回复
热议问题