现在开发iOS无非就是用xib和纯代码开发,不论用什么方式开发都少不了屏幕适配。这只是个人开发中使用的方法也不一定是最好的方法,仅供交流和分享使用。
Xib 屏幕适配
关于xib屏幕适配要注意两点
1.字体大小适配
2.控件约束适配
xib字体适配
UILable 为例子
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UILabel (XibScale)
@end
NS_ASSUME_NONNULL_END
#import "UILabel+XibScale.h"
#import <objc/runtime.h>
#import "FitScaleHelper.h"
@implementation UILabel (XibScale)
+ (void)load {
Method swizeeMethod = class_getInstanceMethod([UILabel class], @selector(d_awakeFromNib));
Method originalMethod = class_getInstanceMethod([UILabel class], @selector(awakeFromNib));
if (!class_addMethod([UILabel class], @selector(awakeFromNib), method_getImplementation(swizeeMethod), method_getTypeEncoding(swizeeMethod))) {
method_exchangeImplementations(originalMethod,swizeeMethod);
} else {
class_replaceMethod(self, @selector(d_awakeFromNib), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
}
}
- (void)d_awakeFromNib {
self.font = [UIFont fontWithDescriptor:self.font.fontDescriptor size:self.font.pointSize * [FitScaleHelper getScaleSize]];
[self d_awakeFromNib];
}
@end
FitScaleHelper
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface FitScaleHelper : NSObject
+ (CGFloat)adaptWidthWithValue:(CGFloat)value;
+ (CGFloat)getScaleSize;
@end
NS_ASSUME_NONNULL_END
#import "FitScaleHelper.h"
#import "Macro.h"
@implementation FitScaleHelper
+ (CGFloat)adaptWidthWithValue:(CGFloat)value
{
return value * [[UIScreen mainScreen] bounds].size.width/kDesignWidth;
}
+ (CGFloat)getScaleSize
{
CGFloat scaleSize = [UIScreen mainScreen].bounds.size.width/kDesignWidth;
return scaleSize;
}
@end
Macro
#ifndef Macro_h
#define Macro_h
// 基准屏幕宽度(iphone 6)
#define kDesignWidth 375.0
// 以屏幕宽度为固定比例关系,来计算对应的值。
#define AdaptW(floatValue) (floatValue*[[UIScreen mainScreen] bounds].size.width/kDesignWidth)
#endif
约束适配
利用IBInspectable关键字和分类
1.写一个NSLayoutConstraint的分类,添加adapterScreen的属性(Bool 值,yes代表需要对屏幕进行等比例适配)
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSLayoutConstraint (XibScale)
@property(nonatomic, assign) IBInspectable BOOL adapterScreen;
@end
NS_ASSUME_NONNULL_END
2.在adapterScreen的set方法里面对NSLayoutConstraint对象的constant值进行换算
#import "NSLayoutConstraint+XibScale.h"
#import <objc/runtime.h>
#import "FitScaleHelper.h"
//定义常量
static char *AdapterScreenKey = "AdapterScreenKey";
@implementation NSLayoutConstraint (XibScale)
- (BOOL)adapterScreen{
NSNumber *number = objc_getAssociatedObject(self, AdapterScreenKey);
return number.boolValue;
}
- (void)setAdapterScreen:(BOOL)adapterScreen {
NSNumber *number = @(adapterScreen);
objc_setAssociatedObject(self, AdapterScreenKey, number, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (adapterScreen){
self.constant = [FitScaleHelper adaptWidthWithValue:self.constant];
}
}
@end
3.将该分类导入到工程中,就可以看到xib所有的约束有adapterScreen的属性了,切换至on,就可以达到想要的等比例适配效果了。
![](https://img.haomeiwen.com/i2416132/33f75911b41db1e7.png)
xib 适配后的效果
![](https://img.haomeiwen.com/i2416132/31dd10a7a6b78e24.png)
纯代码适配
首先修改一下FitScaleHelper文件,增加纯代码字体适配
@implementation FitScaleHelper
+ (CGFloat)adaptWidthWithValue:(CGFloat)value
{
return value * [[UIScreen mainScreen] bounds].size.width/kDesignWidth;
}
+ (CGFloat)getScaleSize
{
CGFloat scaleSize = [UIScreen mainScreen].bounds.size.width/kDesignWidth;
return scaleSize;
}
+ (UIFont *)adaptFontWithValue:(CGFloat)value
{
UIFont *fitFont = [UIFont systemFontOfSize:value * [self getScaleSize]];
return fitFont;
}
@end
在修改一下宏
#ifndef Macro_h
#define Macro_h
// 基准屏幕宽度(iphone 6)
#define kDesignWidth 375.0
// 以屏幕宽度为固定比例关系,来计算对应的值。
#define AdaptW(floatValue) [FitScaleHelper adaptWidthWithValue:floatValue]
// 适配字体
#define AdaptFont(floatValue) [FitScaleHelper adaptFontWithValue:floatValue]
#endif /* Macro_h */
纯代码的字体适配也可以通过RunTime来实现
可以参考
iOS字体适配方案
@interface ScaleCodeController ()
@end
@implementation ScaleCodeController
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.edgesForExtendedLayout = UIRectEdgeBottom;
self.navigationController.view.backgroundColor = [UIColor whiteColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = @"纯代码适配";
[self setupView];
}
- (void)setupView{
UIView *bgView = [UIView new];
bgView.backgroundColor = [UIColor systemGray4Color];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:bgView];
[bgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(AdaptW(40));
make.left.mas_equalTo(AdaptW(16));
make.right.mas_equalTo(AdaptW(-16));
make.height.mas_equalTo(AdaptW(95));
}];
UILabel *label = [UILabel new];
label.text = @"屏幕适配字体";
label.font = AdaptFont(14);
label.backgroundColor = [UIColor systemOrangeColor];
[bgView addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.mas_equalTo(AdaptW(8));
}];
UIView *readView = [UIView new];
readView.backgroundColor = [UIColor redColor];
[bgView addSubview:readView];
[readView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(label.mas_bottom).mas_offset(AdaptW(8));
make.left.mas_equalTo(AdaptW(8));
make.width.height.mas_equalTo(AdaptW(50));
}];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
效果
![](https://img.haomeiwen.com/i2416132/b9dcd07df3bef5a5.png)
网友评论