在做屏幕适配前,首先需要了解iPhone各型号的屏幕,
注:7与7+的屏幕同6与6+
iPad 的屏幕:
接下来,明确一个概念-像素密度PPI(Pixel Per Inch by diagonal),即沿着对角线,每英寸所拥有的像素(Pixel)数目。PPI越高,说明屏幕显示图像的密度越高,即通常所说的分辨率越高。(PPI *对角线)的平方 = 屏幕高的平方+屏幕宽的平方;后来在iPhone4中,采用了Retina显示技术,横、纵向方向像素密度都被放大到2倍,iPhone4与iPhone3具有同样大小的屏幕,但分辨率提升了4倍(1个Point被渲染成1个2x2的像素矩阵)。对于 iOS 开发者来说,iOS 绘制图形的API以point(pt)为单位,在iPhone4-iPhone6中,1个point = 2个pixel,iPhone6+,1个point = 3个pixel。
一、根据屏幕的宽高比例适配
iPhone4~6(+)的屏幕高宽比:
iPhone4(s):分辨率960*640,高宽比1.5
iPhone5(s):分辨率1136*640,高宽比1.775
iPhone6:分辨率1334*750,高宽比1.779
iPhone6+:分辨率1920*1080,高宽比1.778
可选定一个屏幕的宽高为基准,利用宽高比,在不同的屏幕中来进行对控件的位置与控件的宽高进行等比例缩放,但要注意,iPhone4与iPhone5的宽都为320,但高度不同,可以获得宽比例和高比例,同时使用宽高比例。
//获得当前屏幕宽与6的屏宽比例
#define RATIO_W [UIScreen mainScreen].bounds.size.width/375
//获得当前屏幕高与6的屏高比例
#define RATIO_H [UIScreen mainScreen].bounds.size.height/667
//设置frame时使用
#define CGRATIONRect(x,y,w,h) CGRectMake(x*RATIO_W, y*RATIO_H, w*RATIO_W, h*RATIO_H)
二、使用AutoLayout进行屏幕适配
AutoLayout关键就是约束和参照,首先介绍它的一个类方法:+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c
,该方法返回一个NSLayoutConstraint对象;
view1—传入想要添加约束的控件
attr1—传入想要添加约束的方向(枚举)
relation—传入与约束值的关系,大于,等于还是小于
view2—传入被参照对象
attr2—传入被参照对象所被参照的方向
multiplier—传入想要的间距倍数关系
c —传入最终的差值
先简单的创建一个view1
//创建一个视图,背景色为红色
UIView * view1 = [[UIView alloc]init];
view1.backgroundColor = [UIColor redColor];
view1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view1];
//为view1添加约束,距离self.view左边缘20
NSLayoutConstraint * view1Left = [NSLayoutConstraint constraintWithItem:view1 attribute:(NSLayoutAttributeLeft) relatedBy:(NSLayoutRelationEqual) toItem:self.view attribute:(NSLayoutAttributeLeft) multiplier:1.0 constant:20.0];
//为view1添加约束,距离self.view上方20
NSLayoutConstraint * view1Top = [NSLayoutConstraint constraintWithItem:view1 attribute:(NSLayoutAttributeTop) relatedBy:(NSLayoutRelationEqual) toItem:self.view attribute:(NSLayoutAttributeTop) multiplier:1.0 constant:20.0];
//为view1添加约束,宽度为self.view的一半
NSLayoutConstraint * view1Width = [NSLayoutConstraint constraintWithItem:view1 attribute:(NSLayoutAttributeWidth) relatedBy:(NSLayoutRelationEqual) toItem:self.view attribute:(NSLayoutAttributeWidth) multiplier:0.5 constant:0];
//为view1添加约束,高度为30,无参照控件
NSLayoutConstraint * view1Height = [NSLayoutConstraint constraintWithItem:view1 attribute:(NSLayoutAttributeHeight) relatedBy:(NSLayoutRelationEqual) toItem:nil attribute:kNilOptions multiplier:1.0 constant:50.0];
//添加约束至view1的父控件
[self.view addConstraint:view1Left];
[self.view addConstraint:view1Top];
[self.view addConstraint:view1Width];
[self.view addConstraint:view1Height];
再创建一个依赖view1的view2
UIView * view2 = [[UIView alloc]init];
view2.backgroundColor = [UIColor blueColor];
view2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view2];
//为view2添加约束,与view1坐距离相同
NSLayoutConstraint * view2Left = [NSLayoutConstraint constraintWithItem:view2 attribute:(NSLayoutAttributeLeft) relatedBy:(NSLayoutRelationEqual) toItem:view1 attribute:(NSLayoutAttributeLeft) multiplier:1.0 constant:0];
//为view2添加约束,与view1相隔20
NSLayoutConstraint * view2Top = [NSLayoutConstraint constraintWithItem:view2 attribute:(NSLayoutAttributeTop) relatedBy:(NSLayoutRelationEqual) toItem:view1 attribute:(NSLayoutAttributeBottom) multiplier:1.0 constant:20.0];
//为view2添加约束,与view1同宽
NSLayoutConstraint * view2Width = [NSLayoutConstraint constraintWithItem:view2 attribute:(NSLayoutAttributeWidth) relatedBy:(NSLayoutRelationEqual) toItem:view1 attribute:(NSLayoutAttributeWidth) multiplier:1.0 constant:0];
//为view2添加约束,等宽高
NSLayoutConstraint * view2Height = [NSLayoutConstraint constraintWithItem:view2 attribute:(NSLayoutAttributeHeight) relatedBy:(NSLayoutRelationEqual) toItem:view2 attribute:(NSLayoutAttributeWidth) multiplier:1.0 constant:0];
//添加约束至view2的父控件
[self.view addConstraint:view2Left];
[self.view addConstraint:view2Top];
[self.view addConstraint:view2Width];
[view2 addConstraint:view2Height];
使用AutoLayout适配时,需注意不要重复添加约束,也不要有约束冲突,若造成了约束冲突,可添加优先级来解决,优先级的范围是0~1000,数字越大,优先级越高,不设置的情况下默认为1000。
//为view2添加另外的约束,距离self.view底部20,与view2的等宽高约束冲突,若都采用默认优先级,运行证明该约束的优先级更高
NSLayoutConstraint * elseConstraint = [NSLayoutConstraint constraintWithItem:view2 attribute:(NSLayoutAttributeBottom) relatedBy:(NSLayoutRelationEqual) toItem:self.view attribute:(NSLayoutAttributeBottom) multiplier:1.0 constant:20.0];
//设置优先级
UILayoutPriority priority = 500;
//添加优先级
elseConstraint.priority = priority;
//再运行,view2依然等宽高
[self.view addConstraint:elseConstraint];
AutoLayout还提供另外的方法:+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;
返回一个数组。该方法使用的是Visual Format Language,此方法,个人觉得参数太复杂,不好用。
format—传入某种格式构成的字符串,用以表达想要添加的约束;
opts—对齐方式(枚举);
metrics— 一般传入以间距为KEY的字典,KEY要与format参数里所填写的“margin”相同;
views—传入约束中提到的View,也是要传入字典,但是KEY一定要和format参数里所填写的View名字相同;
在format参数中,@”H:”—水平方向;@”V:”—垂直方向;@”|”—边界;@”-“—间隙;@”[]”—括号里是要添加约束的View。
列如创建一个view1
//创建第一个视图,背景色为红色
UIView * view1 = [[UIView alloc]init];
view1.backgroundColor = [UIColor redColor];
view1.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view1];
//设置水平方向约束,距离左边界20,宽50
NSString * hConstrain1 = @"H:|-20-[view(50)]";;
//设置水平方向约束,距离上边界20,高60
NSString * vConstrain1 = @"V:|-20-[view1(60)]";
//生成水平约束
NSArray * arr1 = [NSLayoutConstraint constraintsWithVisualFormat:hConstrain1 options:NSLayoutFormatAlignAllLeft metrics:nil views:@{@"view1":view1}];
//生成竖直约束
NSArray * arr2 = [NSLayoutConstraint constraintsWithVisualFormat:vConstrain1 options:(NSLayoutFormatAlignAllTop) metrics:nil views:@{@"view1":view1}];
//添加约束
[self.view addConstraints:arr1];
[self.view addConstraints:arr2];
创建多个有依赖关系的视图
//创建第二个视图,背景色为红色
UIView * view2 = [[UIView alloc]init];
view2.backgroundColor = [UIColor yellowColor];
view2.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view2];
//创建第三个视图,背景色为红色
UIView * view3 = [[UIView alloc]init];
view3.backgroundColor = [UIColor blueColor];
view3.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:view3];
//设置水平方向约束,距离左边界20,宽50
NSString * hConstrain1 = @"H:|-margin1-[v1(50)]-margin2-[v2(60)]-margin3-[v3(==v1)]";;
//设置水平方向约束,距离上边界20,高60
NSString * vConstrain1 = @"V:|-20-[view1(60)]";
NSLayoutFormatOptions ops = NSLayoutFormatAlignAllTop|NSLayoutFormatAlignAllBottom;
//生成水平约束
NSArray * arr1 = [NSLayoutConstraint constraintsWithVisualFormat:hConstrain1 options:ops metrics:@{@"margin1":@10,@"margin2":@20,@"margin3":@30} views:@{@"v1":view1,@"v2":view2,@"v3":view3}];
//生成竖直约束
NSArray * arr2 = [NSLayoutConstraint constraintsWithVisualFormat:vConstrain1 options:(NSLayoutFormatAlignAllTop) metrics:nil views:@{@"view1":view1}];
//添加约束
[self.view addConstraints:arr1];
[self.view addConstraints:arr2];
三、使用Masonry进行屏幕适配
Masonry的语言简洁,是一款非常受欢迎的屏幕适配框架,Masonry下载地址。Masonry非常容易理解,想要熟练的使用还需要靠自己去实践,这里写了一些基本的用法,大家可以查看Masonry的源码去好好研究。
//创建第一个视图,背景色为红色
UIView * view1 = [[UIView alloc]init];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];
//创建第二个视图,背景色为黄色
UIView * view2 = [[UIView alloc]init];
view2.backgroundColor = [UIColor yellowColor];
[self.view addSubview:view2];
//创建第三个视图,背景色为蓝色
UIView * view3 = [[UIView alloc]init];
view3.backgroundColor = [UIColor blueColor];
[self.view addSubview:view3];
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
//距离坐边界10.0
make.left.equalTo(self.view.mas_left).offset(10.0);
//距离上边界10.0
make.top.equalTo(self.view.mas_top).offset(10.0);
//宽为屏宽的30%
make.width.equalTo(self.view.mas_width).multipliedBy(0.3);
//高为屏高的10%
make.height.equalTo(self.view.mas_height).multipliedBy(0.1);
}];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
//与view1的右边界相邻
make.left.equalTo(view1.mas_right);
//与view1的上边界相同
make.top.equalTo(view1.mas_top);
//宽、高为view1宽相同
make.width.and.height.equalTo(view1);
}];
[view3 mas_makeConstraints:^(MASConstraintMaker *make) {
//与view1的左边界相同
make.leading.equalTo(view1);
//距离view1的下边界10
make.top.equalTo(view1.mas_bottom).offset(10.0);
//view1的宽的80%加10
make.width.equalTo(view1.mas_width).multipliedBy(0.8).offset(10.0);
//view1的高的80%减10
make.height.equalTo(view1.mas_height).multipliedBy(0.8).offset(-10.0);
}];
四、storyboard实现Autolayout
storyboard中实现屏幕适配其实就是将代码视图化,也是通过设置constraint等,这里给大家推荐一遍讲解很详细的博客:storyboard实现Autolayout,希望大家能从中有所收获。