iOS 根据系统设置缩放字体

17 阅读2分钟

1.随着系统比例放大

Swift

extension UILabel {
    func applyGlobalFontScale() {
        let font = self.font ?? UIFont.preferredFont(forTextStyle: .body)
        let fontMetrics = UIFontMetrics(forTextStyle: .body)
        let scaledFont = fontMetrics.scaledFont(for: font)
        self.font = scaledFont
        self.adjustsFontForContentSizeCategory = true
    }
}
 
extension UIButton {
    func applyGlobalFontScale() {
        let font =  self.titleLabel?.font ?? UIFont.preferredFont(forTextStyle: .body)
        let fontMetrics = UIFontMetrics(forTextStyle: .body)
        let scaledFont = fontMetrics.scaledFont(for: font)
        self.titleLabel?.font = scaledFont
        self.titleLabel?.adjustsFontForContentSizeCategory = true
    }
}
 
extension UITextField {
    func applyGlobalFontScale() {
        let font = self.font ?? UIFont.preferredFont(forTextStyle: .body)
        let fontMetrics = UIFontMetrics(forTextStyle: .body)
        let scaledFont = fontMetrics.scaledFont(for: font)
        self.font = scaledFont
        self.adjustsFontForContentSizeCategory = true
    }
}
 
extension UITextView {
    func applyGlobalFontScale() {
        let font = self.font ?? UIFont.preferredFont(forTextStyle: .body)
        let fontMetrics = UIFontMetrics(forTextStyle: .body)
        let scaledFont = fontMetrics.scaledFont(for: font)
        self.font = scaledFont
        self.adjustsFontForContentSizeCategory = true
    }
}

OC

- (void)applyGlobalFontScale {
    UIFont *font = self.font ?: [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:UIFontTextStyleBody];
    UIFont *scaledFont = [fontMetrics scaledFontForFont:font];
    self.font = scaledFont;
    self.adjustsFontForContentSizeCategory = YES;
}

- (void)applyGlobalFontScale {
    UIFont *font = self.titleLabel.font ?: [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:UIFontTextStyleBody];
        UIFont *scaledFont = [fontMetrics scaledFontForFont:font];
    [self.titleLabel setFont:scaledFont];
    self.titleLabel.adjustsFontForContentSizeCategory = YES;
}

- (void)applyGlobalFontScale {
    UIFont *font = self.font ?: [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:UIFontTextStyleBody];
    UIFont *scaledFont = [fontMetrics scaledFontForFont:font];
    self.font = scaledFont;
    self.adjustsFontForContentSizeCategory = YES;
}

- (void)applyGlobalFontScale {
    UIFont *font = self.font ?: [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
    UIFontMetrics *fontMetrics = [UIFontMetrics metricsForTextStyle:UIFontTextStyleBody];
    UIFont *scaledFont = [fontMetrics scaledFontForFont:font];
    self.font = scaledFont;
    self.adjustsFontForContentSizeCategory = YES;
}

2. 用系统比例, 自定义缩放比

获取系统设置的字体缩放比例

let textStyle: UIFont.TextStyle = .body  // 选择合适的字体风格
let font = UIFont.preferredFont(forTextStyle: textStyle)
let fontMetrics = UIFontMetrics(forTextStyle: textStyle)
let scaleFactor = fontMetrics.scaledValue(for: font.pointSize) / font.pointSize

给 SYSTEM_FONT_SCALE 赋予自己的缩放比 创建分类 -- hook 住系统方法 UIFont+Category

#import "UIFont+Category.h"

#import <objc/runtime.h>

@implementation UIFont (Category)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // system
        Method originalMethod = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
        Method swizzledMethod = class_getClassMethod([self class], @selector(swizzled_systemFontOfSize:));
        method_exchangeImplementations(originalMethod, swizzledMethod);

        // bold
        Method originalMethod1 = class_getClassMethod([UIFont class], @selector(boldSystemFontOfSize:));
        Method swizzledMethod1 = class_getClassMethod([self class], @selector(swizzled_boldSystemFontOfSize:));
        method_exchangeImplementations(originalMethod1, swizzledMethod1);

        // fontName
        Method originalMethod2 = class_getClassMethod([UIFont class], @selector(fontWithName:size:));
        Method swizzledMethod2 = class_getClassMethod([self class], @selector(swizzled_fontWithName:size:));
        method_exchangeImplementations(originalMethod2, swizzledMethod2);
    });
}


+ (UIFont *)swizzled_systemFontOfSize:(CGFloat)fontSize {
    CGFloat newFontSize = round(fontSize * SYSTEM_FONT_SCALE);
    UIFont *originalFont = [self swizzled_systemFontOfSize:newFontSize];
    return originalFont;
}

+ (UIFont *)swizzled_boldSystemFontOfSize:(CGFloat)fontSize {
    CGFloat newFontSize = round(fontSize * SYSTEM_FONT_SCALE);
    UIFont *originalFont = [self swizzled_boldSystemFontOfSize:newFontSize];
    return originalFont;
}

+ (UIFont *)swizzled_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
    CGFloat newFontSize = round(fontSize * SYSTEM_FONT_SCALE);
    UIFont *originalFont = [self swizzled_fontWithName:fontName size:newFontSize];
    return originalFont;
}
@end

xib 和 storyboard

hook initWithCoder:

UILabel+Category

#import "UILabel+Category.h"
#import <objc/runtime.h>

@implementation UILabel (Category)

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod = class_getInstanceMethod([self class], @selector(initWithCoder:));
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(swizzled_initWithCoder:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

- (instancetype)swizzled_initWithCoder:(NSCoder *)coder
{
    if ([self swizzled_initWithCoder:coder]) {
        self.font = [UIFont fontWithName:self.font.familyName size:self.font.pointSize];
    }
    return self;
}
@end

UITextField+Category 同上 UITextView+Category 同上

UIButton+Category

#import "UIButton+Category.h"
#import <objc/runtime.h>

@implementation UIButton (Category)
+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod = class_getInstanceMethod([self class], @selector(initWithCoder:));
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(swizzled_initWithCoder:));
        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
} 

- (instancetype)swizzled_initWithCoder:(NSCoder *)coder
{
    if ([self swizzled_initWithCoder:coder]) {
        self.titleLabel.font = [UIFont fontWithName:self.titleLabel.font.familyName size:self.titleLabel.font.pointSize];
    }
    return self;
} 
@end