How to use a custom font with dynamic text sizes in iOS7

前端 未结 12 2014
长情又很酷
长情又很酷 2020-11-29 14:41

In iOS7 there are new API\'s for getting a font that is automatically adjusted to the text size the user has set in their preferences.

It looks something like this to

相关标签:
12条回答
  • 2020-11-29 15:08

    Similar to @bill-weinman's approach, I took the scales, and broke it out into a function that doesn't rely on a given font size of 16.

    /// The font scale for a given font size.
    ///
    /// - seealso: [Source](https://stackoverflow.com/a/33114525/3643020)
    ///
    /// - Parameter fontSize: The font size.
    /// - Returns: The font scale
    public func fontScale(for fontSize: CGFloat) -> CGFloat {
        switch UIApplication.shared.preferredContentSizeCategory {
        case UIContentSizeCategory.accessibilityExtraExtraExtraLarge:    return (fontSize + 8) / fontSize
        case UIContentSizeCategory.accessibilityExtraExtraLarge:         return (fontSize + 7) / fontSize
        case UIContentSizeCategory.accessibilityExtraLarge:              return (fontSize + 6) / fontSize
        case UIContentSizeCategory.accessibilityLarge:                   return (fontSize + 5) / fontSize
        case UIContentSizeCategory.accessibilityMedium:                  return (fontSize + 4) / fontSize
        case UIContentSizeCategory.extraExtraExtraLarge:                 return (fontSize + 3) / fontSize
        case UIContentSizeCategory.extraExtraLarge:                      return (fontSize + 2) / fontSize
        case UIContentSizeCategory.extraLarge:                           return (fontSize + 1) / fontSize
        case UIContentSizeCategory.large:                                return 1.0
        case UIContentSizeCategory.medium:                               return (fontSize - 1) / fontSize
        case UIContentSizeCategory.small:                                return (fontSize - 2) / fontSize
        case UIContentSizeCategory.extraSmall:                           return (fontSize - 3) / fontSize
        default:
            return 1.0
        }
    }
    

    It can then be used with custom fonts like this:

    /// Light font of specified size.
    ///
    /// - Parameter size: Font size.
    /// - Returns: Light font of specified size.
    func lightFont(ofSize size: CGFloat) -> UIFont {
        let scaledSize = size * fontScale(for: size)
    
        return UIFont(name: "HelveticaNeueLTStd-Lt", size: scaledSize)!
    }
    
    0 讨论(0)
  • 2020-11-29 15:10

    Starting from iOS 11 you can programmatically adjust custom fonts configured in visual editor:

    1. Configure your custom font using visual editor
    2. Adjust font size in viewDidLoad method:
    @IBOutlet weak var leftLangLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        leftLangLabel.font = UIFontMetrics.default.scaledFont(for: leftLangLabel.font)
    }
    
    0 讨论(0)
  • 2020-11-29 15:12

    Behind the scenes of that API, apple has some sort of lookup table that returns a specific font family, size, and sometimes symbolic traits (like bold) that (e.g. UIFontTextStyleHeadline) and the user's preferred text size. The latter is a string pulled off of the sharedApplication like this:

    [UIApplication sharedApplication].preferredContentSizeCategory;
    

    (I logged out all the default sizes/fonts/traits for Helvetica-Neue for the various dynamic text sizes). We've since added handling for the accessibility sizes, which is important.

    So all you really have to do is build a similar lookup table. Our designer created a simple spreadsheet for me:

    Font size lookup table

    Notice that we added a couple styles (caption 3 & 4) to have 8 instead of 6 to choose from.

    Then you'll want to put it someplace convenient, like a category on UIFontDescriptor. You'll want your method to return a UIFontDescriptor like Apple's API, so that it's still easy to adjust with symbolic traits, etc.

    My category looks like this:

    UIFontDescriptor+AvenirNext.h

    #import <UIKit/UIKit.h>
    
    extern NSString *const ANUIFontTextStyleCaption3;
    
    @interface UIFontDescriptor (AvenirNext)
    
    +(UIFontDescriptor *)preferredAvenirNextFontDescriptorWithTextStyle:(NSString *)style;
    
    @end
    

    UIFontDescriptor+AvenirNext.m

    #import "UIFontDescriptor+AvenirNext.h"
    
    NSString *const ANUIFontTextStyleCaption3 = @"ANUIFontTextStyleCaption3";
    NSString *const ANUIFontTextStyleCaption4 = @"ANUIFontTextStyleCaption4";
    
    @implementation UIFontDescriptor (AvenirNext)
    +(UIFontDescriptor *)preferredAvenirNextFontDescriptorWithTextStyle:(NSString *)style {
        static dispatch_once_t onceToken;
        static NSDictionary *fontSizeTable;
        dispatch_once(&onceToken, ^{
            fontSizeTable = @{
              UIFontTextStyleHeadline: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @26,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @25,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @24,
                                        UIContentSizeCategoryAccessibilityLarge: @24,
                                        UIContentSizeCategoryAccessibilityMedium: @23,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @23,
                                        UIContentSizeCategoryExtraExtraLarge: @22,
                                        UIContentSizeCategoryExtraLarge: @21,
                                        UIContentSizeCategoryLarge: @20,
                                        UIContentSizeCategoryMedium: @19,
                                        UIContentSizeCategorySmall: @18,
                                        UIContentSizeCategoryExtraSmall: @17,},
    
           UIFontTextStyleSubheadline: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @24,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @23,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @22,
                                        UIContentSizeCategoryAccessibilityLarge: @22,
                                        UIContentSizeCategoryAccessibilityMedium: @21,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @21,
                                        UIContentSizeCategoryExtraExtraLarge: @20,
                                        UIContentSizeCategoryExtraLarge: @19,
                                        UIContentSizeCategoryLarge: @18,
                                        UIContentSizeCategoryMedium: @17,
                                        UIContentSizeCategorySmall: @16,
                                        UIContentSizeCategoryExtraSmall: @15,},
    
                  UIFontTextStyleBody: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @21,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @20,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @19,
                                        UIContentSizeCategoryAccessibilityLarge: @19,
                                        UIContentSizeCategoryAccessibilityMedium: @18,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @18,
                                        UIContentSizeCategoryExtraExtraLarge: @17,
                                        UIContentSizeCategoryExtraLarge: @16,
                                        UIContentSizeCategoryLarge: @15,
                                        UIContentSizeCategoryMedium: @14,
                                        UIContentSizeCategorySmall: @13,
                                        UIContentSizeCategoryExtraSmall: @12,},
              
              UIFontTextStyleCaption1: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @19,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @18,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @17,
                                        UIContentSizeCategoryAccessibilityLarge: @17,
                                        UIContentSizeCategoryAccessibilityMedium: @16,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @16,
                                        UIContentSizeCategoryExtraExtraLarge: @16,
                                        UIContentSizeCategoryExtraLarge: @15,
                                        UIContentSizeCategoryLarge: @14,
                                        UIContentSizeCategoryMedium: @13,
                                        UIContentSizeCategorySmall: @12,
                                        UIContentSizeCategoryExtraSmall: @12,},
              
              UIFontTextStyleCaption2: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @18,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @17,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @16,
                                        UIContentSizeCategoryAccessibilityLarge: @16,
                                        UIContentSizeCategoryAccessibilityMedium: @15,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @15,
                                        UIContentSizeCategoryExtraExtraLarge: @14,
                                        UIContentSizeCategoryExtraLarge: @14,
                                        UIContentSizeCategoryLarge: @13,
                                        UIContentSizeCategoryMedium: @12,
                                        UIContentSizeCategorySmall: @12,
                                        UIContentSizeCategoryExtraSmall: @11,},
              
            ANUIFontTextStyleCaption3: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @17,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @16,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @15,
                                        UIContentSizeCategoryAccessibilityLarge: @15,
                                        UIContentSizeCategoryAccessibilityMedium: @14,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @14,
                                        UIContentSizeCategoryExtraExtraLarge: @13,
                                        UIContentSizeCategoryExtraLarge: @12,
                                        UIContentSizeCategoryLarge: @12,
                                        UIContentSizeCategoryMedium: @12,
                                        UIContentSizeCategorySmall: @11,
                                        UIContentSizeCategoryExtraSmall: @10,},
    
              UIFontTextStyleFootnote: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @16,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @15,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @14,
                                        UIContentSizeCategoryAccessibilityLarge: @14,
                                        UIContentSizeCategoryAccessibilityMedium: @13,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @13,
                                        UIContentSizeCategoryExtraExtraLarge: @12,
                                        UIContentSizeCategoryExtraLarge: @12,
                                        UIContentSizeCategoryLarge: @11,
                                        UIContentSizeCategoryMedium: @11,
                                        UIContentSizeCategorySmall: @10,
                                        UIContentSizeCategoryExtraSmall: @10,},
    
              ANUIFontTextStyleCaption4: @{
                                        UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @15,
                                        UIContentSizeCategoryAccessibilityExtraExtraLarge: @14,
                                        UIContentSizeCategoryAccessibilityExtraLarge: @13,
                                        UIContentSizeCategoryAccessibilityLarge: @13,
                                        UIContentSizeCategoryAccessibilityMedium: @12,
                                        UIContentSizeCategoryExtraExtraExtraLarge: @12,
                                        UIContentSizeCategoryExtraExtraLarge: @11,
                                        UIContentSizeCategoryExtraLarge: @11,
                                        UIContentSizeCategoryLarge: @10,
                                        UIContentSizeCategoryMedium: @10,
                                        UIContentSizeCategorySmall: @9,
                                        UIContentSizeCategoryExtraSmall: @9,},
            };
        });
        
        
        NSString *contentSize = [UIApplication sharedApplication].preferredContentSizeCategory;
        return [UIFontDescriptor fontDescriptorWithName:[self preferredFontName] size:((NSNumber *)fontSizeTable[style][contentSize]).floatValue];
    }
    +(UIFontDescriptor *)preferredAvenirNextDemiBoldFontDescriptorWithTextStyle:(NSString *)style {
        return [[self preferredAvenirNextFontDescriptorWithTextStyle:style] fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold];
    }
    
    +(UIFontDescriptor *)preferredAvenirNextBoldFontDescriptorWithTextStyle:(NSString *)style {
        return [UIFontDescriptor fontDescriptorWithName:[self preferredBoldFontName] size:[self preferredAvenirNextFontDescriptorWithTextStyle:style].pointSize];
    }
    
    +(NSString *)preferredFontName {
        return @"AvenirNext-Medium";
    }
    +(NSString *)preferredBoldFontName {
        return @"AvenirNext-Bold";
    }
    
    @end
    

    We chose to use the same base font AvenirNext-Medium, and then bold and such via symbolic traits, but you could get crazy and specify different weight variants on your font as part of your lookup table as well if you wanted, like AvenirNext-ExtraBold.

    That's all there is to it! We use it like this:

    [UIFont fontWithDescriptor:[UIFontDescriptor preferredAvenirNextFontDescriptorWithTextStyle:UIFontTextStyleHeadline] size: 0]
    
    0 讨论(0)
  • 2020-11-29 15:21

    Try this:

    UIFontDescriptor *userHeadLineFont = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleHeadline];
    CGFloat userHeadLineFontSize = [userHeadLineFont pointSize];
    myFont = [UIFont fontWithName:@"Baskerville" size:userHeadLineFontSize];
    

    But keep in mind that this code is only an approximation (Dynamic Type does much more than just scale font size).

    0 讨论(0)
  • 2020-11-29 15:23

    This is how I update the font of a prefferedFontForTextStyle:

    UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    UIFontDescriptor *fontDesc = [font fontDescriptor];
    fontDesc = [fontDesc fontDescriptorByAddingAttributes:@{UIFontDescriptorNameAttribute : @"Helvetica",
                                                            UIFontDescriptorSizeAttribute : @16}];
    
    font = [UIFont fontWithDescriptor:fontDesc
                                 size:[fontDesc pointSize]];
    
    0 讨论(0)
  • 2020-11-29 15:27

    Just wanted to jump in and say that there's a library out there to help integrate custom fonts and deal with the Dynamic Type size changes. It's called, helpfully, Font (https://github.com/adamyanalunas/Font) and instead of being a magic solution it sets up a structure for handling each custom font differently while removing the boilerplate.

    n.b. I'm the author of this lil' library and I think it's neat.

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