How to calculate actual font point size in iOS 7 (not the bounding rectangle)?

前端 未结 8 1175
一整个雨季
一整个雨季 2020-12-01 15:13

Edit: The linked \"duplicate\" question only deals with calculating text rectangle. I need to calculate actual font size after label scaled it, NOT the string size.<

相关标签:
8条回答
  • 2020-12-01 15:29

    I have the same problem, I need to know the actual size to make that the others UILabels in my UIView match.

    I know that it's not a perfect solution, but perhaps it's useful for you.

    My solution is: instead of use adjustsFontSizeToFitWidth I calculate "manually" the size.

    CGSize initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
    while ( initialSize.width > _label.frame.size.width ) {
        [_label setFont:[_label.font fontWithSize:_label.font.pointSize - 1]];
        initialSize = [_label.text sizeWithAttributes:@{NSFontAttributeName:_label.font}];
    }
    CGFloat actualSize = _label.font.pointSize;
    
    0 讨论(0)
  • 2020-12-01 15:30

    Erik van der Neut's code worked for me, so I translated it in Swift and wrapped it in a UILabel extension:

    extension UILabel {
    
        public func actualFontSize()-> CGFloat {
            let context = NSStringDrawingContext()
            context.minimumScaleFactor = self.minimumScaleFactor
    
            let attributedString = NSAttributedString(string: self.text ?? "", attributes: [NSFontAttributeName: self.font])
            attributedString.boundingRectWithSize(self.frame.size, options: [.UsesLineFragmentOrigin], context: context)
    
            return (self.font.pointSize * context.actualScaleFactor)
        }
    }
    
    0 讨论(0)
  • 2020-12-01 15:31

    Simple solution for one-line UILabel:

    //myLabel - initial label
    
    UILabel *fullSizeLabel = [UILabel new];
    fullSizeLabel.font = myLabel.font;
    fullSizeLabel.text = myLabel.text;
    [fullSizeLabel sizeToFit];
    
    CGFloat actualFontSize = myLabel.font.pointSize * (myLabel.bounds.size.width / fullSizeLabel.bounds.size.width);
    
    //correct, if new font size bigger than initial
    actualFontSize = actualFontSize < myLabel.font.pointSize ? actualFontSize : myLabel.font.pointSize;
    
    0 讨论(0)
  • 2020-12-01 15:36

    The use of minFontSize was deprecated on UILabel in iOS 6, and on the NSString drawing additions in iOS 7. If you want to use it and find the actual font size used, you need to use the deprecated method you mentioned in your question.

    The replacement for minFontSize is minimumScaleFactor. If you want to find the actual scale factor used, you need to create an NSStringDrawingContext and pass it in the boundingRectWithSize:options:attributes:context: message, like this:

    NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
    context.minimumScaleFactor = 0.7;
    [label.text boundingRectWithSize:CGSizeMake(maxWidth, HUGE_VAL)
        options:NSStringDrawingUsesLineFragmentOrigin
        attributes:@{
            NSFontAttributeName: font
        } context:context];
    CGFloat actualFontSize = font.pointSize * context.actualScaleFactor;
    
    0 讨论(0)
  • 2020-12-01 15:36

    Expanding on Ferran's answer

    To expand to fill width or height, whichever it hits first

    Swift version

    func getFontSizeToFitFrameOfLabel(label: UILabel) -> CGFloat
    {
        var initialSize : CGSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])
    
        if initialSize.width > label.frame.size.width ||
           initialSize.height > label.frame.size.height
        {
            while initialSize.width > label.frame.size.width ||
                  initialSize.height > label.frame.size.height
            {
                label.font = label.font.fontWithSize(label.font.pointSize - 1)
                initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])
            }
        } else {
            while initialSize.width < label.frame.size.width &&
                  initialSize.height < label.frame.size.height
            {
                label.font = label.font.fontWithSize(label.font.pointSize + 1)
                initialSize = label.text!.sizeWithAttributes([NSFontAttributeName : label.font])
            }
            // went 1 point too large so compensate here
            label.font = label.font.fontWithSize(label.font.pointSize - 1)
        }
        return label.font.pointSize;
    }
    

    Then do something like this to use it (say your label is named title1Label)

     title1Label.frame = CGRect(x: 0.0, y: 0.0, width: view.frame.size.width, height: view.frame.size.height)
     // sets font to some nonzero size to begin with, it will change up or down to fit the label's frame
     title1Label.font = UIFont(name: "Super Mario 256", size: 45.0)
     title1Label.font = title1Label.font.fontWithSize(getFontSizeToFitFrameOfLabel(title1Label))
     // resize height to be a little larger than the font height
     title1Label.frame.size.height = title1Label.font.pointSize*1.3
    

    Objective C version:

    - (CGFloat) maxFontSize:(UILabel *)label{
       CGSize initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
    
       if (initialSize.width > label.frame.size.width ||
           initialSize.height > label.frame.size.height)
       {
           while (initialSize.width > label.frame.size.width ||
                  initialSize.height > label.frame.size.height)
           {
               [label setFont:[label.font fontWithSize:label.font.pointSize - 1]];
               initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
           }
       } else {
           while (initialSize.width < label.frame.size.width &&
                  initialSize.height < label.frame.size.height)
           {
               [label setFont:[label.font fontWithSize:label.font.pointSize + 1]];
               initialSize = [label.text sizeWithAttributes:@{NSFontAttributeName:label.font}];
           }
           // went 1 point too large so compensate here
           [label setFont:[label.font fontWithSize:label.font.pointSize - 1]];
       }
       return label.font.pointSize;
    }
    
    0 讨论(0)
  • 2020-12-01 15:39

    Distilled from Julius Bahr's answer on this page, this method works perfectly for getting the actual font size after it has been automatically adjusted:

    - (CGFloat)getActualFontSizeForLabel:(UILabel *)label
    {
        NSStringDrawingContext *labelContext = [NSStringDrawingContext new];
        labelContext.minimumScaleFactor = label.minimumScaleFactor;
    
        NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:label.text attributes:@{ NSFontAttributeName: label.font }];
        [attributedString boundingRectWithSize:label.frame.size
                                       options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                                       context:labelContext];
    
        CGFloat actualFontSize = label.font.pointSize * labelContext.actualScaleFactor;
        return actualFontSize;
    }
    

    I am using this in my application to get the font sizes for three different labels for which I need to keep the sizes in synch while still allowing them to auto-shrink for localized translations that can be quite a bit longer than their original English counterparts.

    I call that method once for each label, and then if they are not all the same value, I set the label's font sizes to the minimum of the three.

    0 讨论(0)
提交回复
热议问题