1、引言
由于公司产品经理提出的需求,说不同机型下的字体变化不怎么明显,尤其是iPhone 5s,字体比较大,固定的控件大小、位置就显得比较拥挤;其他机型则还好,显示比较正常。
2、效果
图13、方案
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文件很多的话,就非常的麻烦。
网友评论