iOS基础知识补充

UILabel的字体大小根据机型自动适配

2018-04-03  本文已影响197人  施忆

1、引言

由于公司产品经理提出的需求,说不同机型下的字体变化不怎么明显,尤其是iPhone 5s,字体比较大,固定的控件大小、位置就显得比较拥挤;其他机型则还好,显示比较正常。

2、效果

图1

3、方案

1、分纯代码和XIB/SB

1.纯代码

//初始化
- (void)viewDidLoad {
    [super viewDidLoad];
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 25)];
    label.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2-100);
    CGFloat multiple = [self fontMultiple];
    label.font = [UIFont systemFontOfSize:17.0*multiple];
    label.text = @"①自动适配文字大小";
    label.textAlignment = NSTextAlignmentCenter;
    label.textColor = [UIColor blackColor];
    [self.view addSubview:label];
}
//倍数
- (CGFloat)fontMultiple
{
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    if (width == 320) {
        return FONT_IPHONE_5S;//0.7
    }
    else if (width == 375) {
        return FONT_IPHONE_6;//1.0
    }
    else if (width == 414) {
        return FONT_IPHONE_6P;//1.3
    }
    else {
        return FONT_IPHONE_OTHER;//1.1
    }
}

2.XIB/SB


图2
- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    if (IS_IPHONE_5) {
        _textLabel.font = [UIFont systemFontOfSize:12];
    }
    //XIB/SB中默认设置就是6和6p的文字大小
    if (IS_iPhoneX) {
        _textLabel.font = [UIFont systemFontOfSize:13];
    }
}
2、使用分类+runtime交换方法实现

关于runtime的具体实战请跳转:传送门
1.UIFont

+ (void)load
{
    [self exchangeMethod:@selector(systemFontOfSize:) with:@selector(SY_systemFontOfSize:)];
}

+ (UIFont *)SY_systemFontOfSize:(CGFloat)fontSize
{
    //这里并不是循环调用,+load里已经把这方法与系统的方法交换了,因此这里调用的是系统方法
    CGFloat multiple = [self fontMultiple];
    UIFont *font = [self SY_systemFontOfSize:fontSize*multiple];
    return font;
}

+ (CGFloat)fontMultiple
{
    CGFloat width = [UIScreen mainScreen].bounds.size.width;
    if (width == 320) {
        return FONT_IPHONE_5S;
    }
    else if (width == 375) {
        return FONT_IPHONE_6;
    }
    else if (width == 414) {
        return FONT_IPHONE_6P;
    }
    else {
        return FONT_IPHONE_OTHER;
    }
}

+ (BOOL)exchangeMethod:(SEL)systemSel with:(SEL)newSel
{
    Class class = object_getClass(self);
    Method originalMethod = class_getInstanceMethod(class, systemSel);
    Method newMethod = class_getInstanceMethod(class, newSel);
    if (!originalMethod || !newMethod) return NO;
    method_exchangeImplementations(originalMethod, newMethod);
    return YES;
}

2.UILabel

+ (void)load
{
    [[self class] exchangeMethod:@selector(initWithCoder:) with:@selector(SY_initWithCoder:)];
}

- (id)SY_initWithCoder:(NSCoder *)coder
{
    [self SY_initWithCoder:coder];
    
    CGFloat fontSize = self.font.pointSize;
    self.font = [UIFont systemFontOfSize: fontSize];
    
    return self;
}

+ (BOOL)exchangeMethod:(SEL)systemSel with:(SEL)newSel
{
    Method originalMethod = class_getInstanceMethod(self, systemSel);
    Method newMethod = class_getInstanceMethod(self, newSel);
    if (!originalMethod || !newMethod) return NO;
    
    class_addMethod(self,
                    systemSel,
                    class_getMethodImplementation(self, systemSel),
                    method_getTypeEncoding(originalMethod));
    class_addMethod(self,
                    newSel,
                    class_getMethodImplementation(self, newSel),
                    method_getTypeEncoding(newMethod));
    
    method_exchangeImplementations(class_getInstanceMethod(self, systemSel),
                                   class_getInstanceMethod(self, newSel));
    return YES;
}
3、两种方案的对比

虽然实现的结果都一样,但很明显,第二种方案是最好的,因为只要在项目中加入这两个分类,就可以实现所有的(无论纯代码还是XIB/SB)label文字根据屏幕自动适配。第一种方案,在纯代码下可以使用,但XIB文件很多的话,就非常的麻烦。

4、Demo下载

gitub下载链接

上一篇下一篇

猜你喜欢

热点阅读