美文网首页
利用runtime 对项目全局字体适配

利用runtime 对项目全局字体适配

作者: YannChee | 来源:发表于2018-01-25 18:27 被阅读46次

迭代以前旧的项目,整个项目使用了纯代码,storyboard,xib混合开发,而且美工的设计稿最开始是采用iPhone5的尺寸进行设计的,后来又换成了 iPhone6的尺寸做设计稿
设计稿整体字体偏小,要求在iPhone6和6Plus机型上做适当放大

我的办法是:

1.先创建一个工具类,用于处理字体放大规则:

最开始想根据 屏幕比例系数 [UIScreen mainScreen].bounds.size.width / 320.0
进行等比放大,但是放大后显示效果不太美观协调,后与美工商议,iPhone6尺寸手机放大1pt,6plus尺寸放大2pt

@interface QYFontFitTool : NSObject
/** 采用iPhone5 设计的尺寸 */
+ (CGFloat)fontSizeBase320Screen:(CGFloat)fontSize;

/** 采用iPhone6 设计的尺寸 */
+ (CGFloat)fontSizeBase375Screen:(CGFloat)fontSize;

@end
@implementation QYFontFitTool
/** 采用iPhone5 设计的尺寸 */
+ (CGFloat)fontSizeBase320Screen:(CGFloat)fontSize {
    CGFloat newFontSize = fontSize;
    //
    if ([UIScreen mainScreen].bounds.size.width <= 320){ // iPhone5 及以下机型
        return  newFontSize;
    } else if ([UIScreen mainScreen].bounds.size.width <= 375 && [UIScreen mainScreen].bounds.size.width > 320){ // iPhone6
        newFontSize = fontSize + 1;
    } else if ([UIScreen mainScreen].bounds.size.width <= 414 && [UIScreen mainScreen].bounds.size.width > 375){ // iPhone6Plus
        newFontSize = fontSize + 2;
    } else if ([UIScreen mainScreen].bounds.size.width > 414 ){ // 未知机型
        newFontSize = fontSize + 2;
    }
    return  newFontSize;
}

/** 采用iPhone6 设计的尺寸 */
+ (CGFloat)fontSizeBase375Screen:(CGFloat)fontSize {
    CGFloat newFontSize = fontSize;
    //
    if ([UIScreen mainScreen].bounds.size.width <= 320){ // iPhone5 及以下机型
        newFontSize = fontSize - 1;
    } else if ([UIScreen mainScreen].bounds.size.width <= 375 && [UIScreen mainScreen].bounds.size.width > 320){ // iPhone6
        return  newFontSize;
    } else if ([UIScreen mainScreen].bounds.size.width <= 414 && [UIScreen mainScreen].bounds.size.width > 375){ // iPhone6Plus
        newFontSize = fontSize + 1;
    } else if ([UIScreen mainScreen].bounds.size.width > 414 ){ // 未知机型
        newFontSize = fontSize + 1;
    }
    return  newFontSize;
}
@end

2.给UIFont添加分类,利用runtime替换系统的设置字体的方法 systemFontOfSize: 和 fontWithName:size:

例如:分类名 UIFont+QYAdapt

@implementation UIFont (QYAdapt)

+(void)load{
    //获取替换后的类方法
    Method newMethod1 = class_getClassMethod([self class], @selector(qy_systemFontOfSize:));
    Method newMethod2 = class_getClassMethod([self class], @selector(qy_fontWithName:size:));

    //获取替换前的类方法
    Method origMethod1 = class_getClassMethod([self class], @selector(systemFontOfSize:));
    Method origMethod2 = class_getClassMethod([self class], @selector(fontWithName:size:));

    //然后交换类方法
    method_exchangeImplementations(newMethod1, origMethod1);
    method_exchangeImplementations(newMethod2, origMethod2);
}

+ (UIFont *)qy_systemFontOfSize:(CGFloat)fontSize {
    CGFloat newFontSize = [QYFontFitTool fontSizeBase320Screen:fontSize];
    UIFont *newFont = [UIFont qy_systemFontOfSize:newFontSize];
    return newFont;
}

+ (nullable UIFont *)qy_fontWithName:(NSString *)fontName size:(CGFloat)fontSize {
    CGFloat newFontSize = [QYFontFitTool fontSizeBase320Screen:fontSize];
    //
    UIFont *newFont = [UIFont qy_fontWithName:fontName size:newFontSize];
    return newFont;
}

@end

此时,界面中大部分字体大小都被改掉了,但是使用xib和storyboard创建lable,不会执行 systemFontOfSize: 或 fontWithName:size: 方法,所以

3.给UILable创建分类,利用runtime替换系统 initWithCoder: 方法

例如 :UILabel+QYAdaptedFont

@implementation UILabel (QYAdaptedFont)

+(void)load{
    //获取替换后的类方法
    Method newMethod1 = class_getInstanceMethod([self class], @selector(qy_initWithCoder:));
   //  Method newMethod2 = class_getInstanceMethod([self class], @selector(qy_initWithFrame:));
    
    //获取替换前的类方法
    Method origMethod1 = class_getInstanceMethod([self class], @selector(initWithCoder:));
//    Method origMethod2 = class_getInstanceMethod([self class], @selector(initWithFrame:));

    //然后交换类方法
    method_exchangeImplementations(newMethod1, origMethod1);
//    method_exchangeImplementations(newMethod2, origMethod2);
}

- (instancetype)qy_initWithCoder:(NSCoder *)aDecoder {
    [self qy_initWithCoder:aDecoder];
    if (self && [self isKindOfClass:[UILabel class]]) {
        CGFloat fontSize = self.font.pointSize ;
        // UIFont *newFont = [UIFont systemFontOfSize:fontSize];这个方法不适用于项目使用了其它字体,所以使用下面那个方法
       UIFont *newFont = [UIFont fontWithName:self.font.fontName size:fontSize];
        self.font = newFont;
    } 
    return self;
}

@end

4.看到这里,肯定有人会问:为什么不直接在UILable分类中,再交换系统的 initWithFrame: 方法啊,这样只需要一个UILable分类就行了,用不着再给UIFont添加分类了😂,?

其实,我也交换了系统的 initWithFrame 啊,但是不起作用啊?我也不知道什么原因啊🤣 ,如果有人知道的话,还请麻烦告知一下🤣

代码如下:

- (instancetype)qy_initWithFrame:(CGRect)frame {
        [self qy_initWithFrame:frame];
        if (self && [self isKindOfClass:[UILabel class]]) {
            CGFloat newFontSize = self.font.pointSize + 8; // 8是瞎写的,方便字体对比明显
            UIFont *newFont = [UIFont systemFontOfSize:newFontSize];
            self.font = newFont;
        }
        return self;
}

相关文章

网友评论

      本文标题:利用runtime 对项目全局字体适配

      本文链接:https://www.haomeiwen.com/subject/xoxbaxtx.html