iOS7: Can we use other than Helvetica Neue fonts with Dynamic Type?

后端 未结 2 1216
别那么骄傲
别那么骄傲 2021-02-03 11:25

We are designing an app for iOS7 and our designer wants to use non-default font (Avenir), but I dont want to loose Dynamic Type functionality. As I understand Dynamic Type can o

相关标签:
2条回答
  • 2021-02-03 11:38

    As far as I understood [UIFont preferredFontForTextStyle:] returns a font with fixed size for a particular font style regardless of text view default size. I expect that changing text size in Settings will change text sizes in my app by some delta instead of setting fixed value. As noted in Text Programming Guide for iOS,

    The actual font used for the purpose described by a text style can vary based on a number of dynamic considerations, including the user’s content size category preference, which is represented by the UIApplication property preferredContentSizeCategory.

    I noticed that property preferredContentSizeCategory changes in response to setting text size in Settings.

    It’s also important to observe the UIContentSizeCategoryDidChangeNotification so that you can re-layout the text when the user changes the content size category. When your app receives that notification, it should send the invalidateIntrinsicContentSize message to views positioned by Auto Layout or send setNeedsLayout to user interface elements positioned manually. And it should invalidate preferred fonts or font descriptors and acquire new ones as needed.

    So, my idea is to observe appropriate notification, calculate size delta based on preferredContentSizeCategory property and apply delta to text view's default font size (which was set in IB or programmatically).


    PreferredFontLabel.h

    @interface PreferredFontLabel : UILabel
    
    @property (nonatomic) UIFontDescriptor *defaultFontDescriptor;
    
    @end
    

    PreferredFontLabel.m

    #import "PreferredFontLabel.h"
    #import "UIApplication+ContentSize.h"
    
    @implementation PreferredFontLabel
    
    - (id)init
    {
        self = [super init];
        if (self) {
            [self setup];
        }
        return self;
    }
    
    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            [self setup];
        }
        return self;
    }
    
    - (id)initWithCoder:(NSCoder *)aDecoder
    {
        self = [super initWithCoder:aDecoder];
        if (self) {
            [self setup];
        }
        return self;
    }
    
    - (void)setup
    {
        self.defaultFontDescriptor = self.font.fontDescriptor;
    
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(contentSizeCategoryDidChange)
         name:UIContentSizeCategoryDidChangeNotification
         object:nil];
    
        [self contentSizeCategoryDidChange];
    }
    
    - (void)setDefaultFontDescriptor:(UIFontDescriptor *)defaultFontDescriptor
    {
        _defaultFontDescriptor = defaultFontDescriptor;
    
        [self contentSizeCategoryDidChange];
    }
    
    - (void)contentSizeCategoryDidChange
    {
        CGFloat preferredSize = [self.defaultFontDescriptor.fontAttributes[UIFontDescriptorSizeAttribute] floatValue];
        preferredSize += [UIApplication sharedApplication].contentSizeDelta;
    
        self.font = [UIFont fontWithDescriptor:self.defaultFontDescriptor size:preferredSize];
        [self invalidateIntrinsicContentSize];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIContentSizeCategoryDidChangeNotification object:nil];
    }
    
    @end
    

    UIApplication+ContentSize.h

    @interface UIApplication (ContentSize)
    
    @property (nonatomic, readonly) NSInteger contentSizeDelta;
    
    @end
    

    UIApplication+ContentSize.m

    #import "UIApplication+ContentSize.h"
    
    @implementation UIApplication (ContentSize)
    
    - (NSInteger)contentSizeDelta
    {
        static NSArray *contentSizeCategories;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            contentSizeCategories = @[UIContentSizeCategoryExtraSmall,
                                      UIContentSizeCategorySmall,
                                      UIContentSizeCategoryMedium,
                                      UIContentSizeCategoryLarge,
                                      UIContentSizeCategoryExtraLarge,
                                      UIContentSizeCategoryExtraExtraLarge,
                                      UIContentSizeCategoryExtraExtraExtraLarge
                                      UIContentSizeCategoryAccessibilityMedium,
                                      UIContentSizeCategoryAccessibilityLarge,
                                      UIContentSizeCategoryAccessibilityExtraLarge,
                                      UIContentSizeCategoryAccessibilityExtraExtraLarge,
                                      UIContentSizeCategoryAccessibilityExtraExtraExtraLarge];
        });
    
        // assume UIContentSizeCategoryLarge is default category
        NSInteger contentSizeDelta = [contentSizeCategories indexOfObject:self.preferredContentSizeCategory];
    
        if(contentSizeDelta != NSNotFound) {
            contentSizeDelta -= [contentSizeCategories indexOfObject:UIContentSizeCategoryLarge];
    
            return contentSizeDelta;
        } else {
            return 0;
        }
    }
    
    @end
    

    I added attributed string support, demo is available on GitHub

    0 讨论(0)
  • 2021-02-03 11:58

    example with custom font.

    https://github.com/jszumski/dynamic-type

    See @implementation UIFont (AvenirContentSize)

    for how to adjust a font to match the default sizes

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