iOS的屏幕适配之Autoresizing、Autolayout、VFL、Masonry

来源:互联网 发布:淘宝店一件代发赚钱么 编辑:程序博客网 时间:2024/05/22 05:14

一、苹果产品的发行

机型 预装系统 iPhone发行时间 对应Xcode iPhone4 iOS 4 2010年06月08日 Xcode3+ iPhone4S iOS 5 2011年10月04日 Xcode4 (4.0收费,引入ARC) iPhone5 iOS 6 2012年09月21日 Xcode4+ (4.1之后免费,引入Autolayout) iPhone5S iOS 7 2013年09月20日 Xcode5 iPhone 6/6 Plus iOS 8 2014年10月10日 Xcode6 iPhone 6S/6S Plus iOS 9 2015年09月10日 Xcode7

二、设备的分辨率

设备 尺寸 像素 点 iPhone \ iPhone 3G \ iPhone 3GS 3.5 inch 320 x 480 320 x 480 iPhone 4 \ iPhone 4S 3.5 inch 640 x 960 320 x 480 iPhone 5 \ iPhone 5C \ iPhone 5S 4.0 inch 640 x 1136 320 x 568 iPhone6 4.7 inch 750 x 1334 375 x 667 iPhone6 plus 5.5 inch 1242 x 2208 414 x 736 iPad \ iPad2 9.7 inch 768 x 1024 768 x 1024 iPad 3(The new iPad) \ iPad4 \ iPad Air 9.7 inch 1536 x 2048 768 x 1024 iPad Mini 7.9 inch 768 x 1024 768 x 1024 iPad Mini 2(iPad Mini with retina display) 7.9 inch 1536 x 2048 768 x 1024

三、屏幕适配

  1. iPhone4S之前没有屏幕适配,因为屏幕尺寸不变,全部用frame、bounds、center进行布局。
  2. iphone5之后才开始有屏幕适配。

四、Autoresizing

  1. iPad的出现和iPhone横屏的出现,出现Autoresizing技术
  2. Autoresizing让横竖屏适配相对于用frame、bounds、center进行布局简单
  3. 使用Autoresizing的前提是:关闭Autolayout功能;因为有些功能重复
  4. 局限性
    - 只能解决子控件跟父控件的相对关系问题
    - 不能解决兄弟控件的相对关系问题
  5. 当控件的的autoresizesSubviews是YES时,(默认是YES),那么UIView对象的子控件会根据子控件自身的autoresizingMask属性值来自动适应与其父控件之间的位置和大小
  6. storyboard或xib下使用Autoresizing,宽高和宽度的自动调整:实线代表选中,左右上下间距的自动调整:虚线代表选中


    关闭自动布局


这里写图片描述


  1. 纯代码使用Autoresizing
---------- UIViewAutoresizing类型,有两个尖号<<代表可以复选,复选用竖杠隔开typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {    //不自动调整    UIViewAutoresizingNone                 = 0,    //自动按与父控件比例调整与父控件左边的距离,且与父控件右边的距离不变    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,    //自动按与父控件比例调整与父控件的右边距离,且与父控件左边的距离不变    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,    //自动按与父控件比例调整与父控件的顶部距离,且与父控件底部的距离不变    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,    //自动按与父控件比例调整与父控件的底部距离,且与父控件顶部的距离不变    UIViewAutoresizingFlexibleBottomMargin = 1 << 5    //自动与父控件按比例调整宽度    UIViewAutoresizingFlexibleWidth        = 1 << 1,    //自动与父控件按比例调整高度    UIViewAutoresizingFlexibleHeight       = 1 << 4,};---------- Autoresizing的使用 #import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {  [super viewDidLoad];  //创建控件,做为父控件  UIView *viewSuper = [[UIView alloc] initWithFrame:CGRectMake(40, 50, 200, 200)];  viewSuper.backgroundColor = [UIColor greenColor];  [self.view addSubview:viewSuper];  //创建控件,做为子控件  UIView *viewSub = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 50, 100)];  viewSub.backgroundColor = [UIColor orangeColor];  [viewSuper addSubview:viewSub];  //autoresizesSubviews的默认值为YES  //当值为NO时,不会根据子控件的autoresizingMask属性值来自动调整  //viewSuper.autoresizesSubviews = NO;  //自动按照比例调整与父控件的左间距和自动按比例调整宽度  viewSub.autoresizingMask =   UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;}//随机改变父控件的宽高,测试调整效果- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  //arc4random_uniform()是取随机数  CGFloat w = 200 + arc4random_uniform(100);  CGFloat h = 200 + arc4random_uniform(100);  [[self.view.subviews lastObject] setFrame:CGRectMake(40, 40, w, h)];}@end

五、Autolayout
(一).Autolayout的2个核心概念
1.参照:参照是指一个约束是根据那个控件来计算约束的,做为参照的控件位置和尺寸大小必须明确
2.约束:约束相当于控件的Frame,用来明确控件所处的位置和控件的的尺寸大小

(二).Autolayout核心计算公式
约束的计算方法:obj1.property =(<=或>=)(obj2.property * multiplier)+ constant
解析:
=: 等号可以根据需求改为:小于等于或大于等于
obj1:控件
property:左边线,右边线,垂直中心线,上边线,下边线,水平中心线,高度,宽度等的约束值
multiplier:倍数
constant:偏移量

(二).注意:
1.约束的本质:用来明确控件所处的位置和控件的的尺寸大小
2.约束和Frame类似,Frame也是用来确定位置和尺寸的大小
3.给一个控件加约束,要么不加,要么加全了;只要给控件添加一个约束,就要加全必要约束,要让控件明确的知道它自己的尺寸和所处的位置,苹果鼓励开发者尽量用Autolayout,忘掉Frame
4.Updata Frames:设置约束后更新Frame;如果约束不全,更新之后控件就会找不到
5.控件UILable很特殊,只约束它的位置,不约束尺寸大小,系统会自动添加宽度和高度约束,这个特性可以用于设置lable的宽度或高度随内容的变化而变化

(三).storyboard和xib下的设置

1.Autolayout的警告和错误
(1).警告
控件的frame不匹配所添加的约束
比如:约束控件的宽度为100, 而控件现在的宽度是110
(2).错误
a.缺乏必要的约束
比如:只约束了宽度和高度, 没有约束具体的位置
b.两个约束冲突
比如:1个约束控件的宽度为100, 1个约束控件的宽度为110

2.添加约束时,系统会自动以Top Layout Guide和Bottom Layout Guide两条线做为约束的参照物,这两天线是系统自动创建时就添加的
这里写图片描述


这里写图片描述


3.约束的属性面板:可以在这个面板修改约束
这里写图片描述


4.Constrain to margins:选中就默认在左右两边各加上16个像素
这里写图片描述


5.更新约束(一)
(1).成功添加就就马上更新
这里写图片描述


(2.)手动更新
这里写图片描述


6.拖拽添加约束
这里写图片描述


这里写图片描述


(四).代码实现Autolayout
1.实现步骤
(1).先禁止autoresizing功能,设置view的下面属性为NO

view.translatesAutoresizingMaskIntoConstraints = NO;

(2).利用NSLayoutConstraint类创建具体的约束对象
创建约束对象的常用方法:

+(instancetype)constraintWithItem:(id)view1                         attribute:(NSLayoutAttribute)attr1                         relatedBy:(NSLayoutRelation)relation                            toItem:(id)view2                         attribute:(NSLayoutAttribute)attr2                        multiplier:(CGFloat)multiplier                          constant:(CGFloat)c;/**解析:     view1 :要约束的控件     attr1 :约束的类型(做怎样的约束)  relation :与参照控件之间的关系     view2 :参照的控件     attr2 :约束的类型(做怎样的约束)multiplier :乘数         c :常量计算公式:attr1 =(<=或>=) attr2 * multiplier + c**/

(3).添加约束对象到相应的view上

- (void)addConstraint:(NSLayoutConstraint *)constraint;- (void)addConstraints:(NSArray *)constraints;

2.添加约束的规则
(1).对于两个同层级view之间的约束关系,添加到它们的父view上
这里写图片描述


(2).对于两个不同层级view之间的约束关系,添加到他们最近的共同父view上
这里写图片描述


(3).对于有层次关系的两个view之间的约束关系,添加到层次较高的父view上
这里写图片描述


3.注意
(a).要先禁止autoresizing功能,设置view的translatesAutoresizingMaskIntoConstraints属性为NO;不然系统会自动把Autoresizing的值转换成约束
(b).添加约束之前,一定要保证相关控件都已经在各自的父控件上
(c).不用再给view设置frame
(d).添加约束不要添加错了控件
(e).一般报错原因是:约束冲突或者约束不完整
4.编程举例

#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {  [super viewDidLoad];  //创建一个蓝色的View,不用设置Frame,设置了可能会起冲突  UIView *blueView = [[UIView alloc] init];  blueView.backgroundColor = [UIColor blueColor];  //必须要设置为NO,默认是YES,在YES的时,系统会自动把Autoresizing的值转换成约束  blueView.translatesAutoresizingMaskIntoConstraints = NO;  [self.view addSubview: blueView];  //创建一个红色的View,不用设置Frame,设置了可能会起冲突  UIView *redView = [[UIView alloc] init];  redView.backgroundColor = [UIColor redColor];  //必须要设置为NO,默认是YES,在YES的时,系统会自动把Autoresizing的值转换成约束  redView.translatesAutoresizingMaskIntoConstraints = NO;  [self.view addSubview:redView];#pragma mark - 设置蓝色的约束  //给蓝色View添加约束:顶部距离父控件上边框50像素  NSLayoutConstraint *blueTopLayout = [NSLayoutConstraint                                       constraintWithItem:blueView                                                attribute:NSLayoutAttributeTop                                                relatedBy:NSLayoutRelationEqual                                                   toItem:self.view                                                attribute:NSLayoutAttributeTop                                               multiplier:1.0                                                 constant:50];  [self.view addConstraint:blueTopLayout];  //给蓝色View添加约束:左边距离父控件左边框180像素  NSLayoutConstraint *blueLeftLayout = [NSLayoutConstraint                                        constraintWithItem:blueView                                                 attribute:NSLayoutAttributeLeft                                                 relatedBy:NSLayoutRelationEqual                                                    toItem:self.view                                                 attribute:NSLayoutAttributeLeft                                                multiplier:1.0                                                  constant:80];  [self.view addConstraint:blueLeftLayout];  //给蓝色View添加约束:宽度为100个像素  NSLayoutConstraint *blueWidthLayout = [NSLayoutConstraint                                         constraintWithItem:blueView                                                  attribute:NSLayoutAttributeWidth                                                  relatedBy:NSLayoutRelationEqual                                                     toItem:nil                                                  attribute:NSLayoutAttributeNotAnAttribute                                                 multiplier:0.0                                                   constant:100];  [blueView addConstraint:blueWidthLayout];  //给蓝色View添加约束:高度为100个像素  NSLayoutConstraint *blueHeightLayout = [NSLayoutConstraint                                          constraintWithItem:blueView                                                   attribute:NSLayoutAttributeHeight                                                   relatedBy:NSLayoutRelationEqual                                                      toItem:nil                                                   attribute:NSLayoutAttributeNotAnAttribute                                                  multiplier:0.0                                                    constant:100];  [blueView addConstraint:blueHeightLayout];#pragma mark - 设置红色的约束  //给红色View添加约束:宽度为100个像素  NSLayoutConstraint *redWidthLayout = [NSLayoutConstraint                                        constraintWithItem:redView                                                 attribute:NSLayoutAttributeWidth                                                 relatedBy:NSLayoutRelationEqual                                                    toItem:nil                                                attribute:NSLayoutAttributeNotAnAttribute                                               multiplier:0.0                                                 constant:100];  //给红色View添加约束:高度为100个像素  NSLayoutConstraint *redHeightLayout = [NSLayoutConstraint                                         constraintWithItem:redView                                                  attribute:NSLayoutAttributeHeight                                                  relatedBy:NSLayoutRelationEqual                                                     toItem:nil                                                  attribute:NSLayoutAttributeNotAnAttribute                                                 multiplier:0.0                                                   constant:100];  //用数组的方式批量添加约束  [redView addConstraints:@[redWidthLayout,redHeightLayout]];  //给红色View添加约束:红色的左边线距离蓝色的右边线距0个像素  NSLayoutConstraint *redLeftLayout = [NSLayoutConstraint                                       constraintWithItem:redView                                                attribute:NSLayoutAttributeLeft                                                relatedBy:NSLayoutRelationEqual                                                   toItem:blueView                                                attribute:NSLayoutAttributeRight                                               multiplier:1.0                                                 constant:0];  //给红色View添加约束:红色的上边线与蓝色的上边线对齐  NSLayoutConstraint *redTopLayout = [NSLayoutConstraint                                         constraintWithItem:redView                                                  attribute:NSLayoutAttributeTop                                                  relatedBy:NSLayoutRelationEqual                                                     toItem:blueView                                                  attribute:NSLayoutAttributeTop                                                 multiplier:1.0                                                   constant:0];  //用数组的方式批量添加约束  [self.view addConstraints: @[redLeftLayout,redTopLayout]];}@end

六、VFL语言
1.VFL全称是Visual Format Language,翻译过来是“可视化格式语言”
2.VFL是苹果公司为了简化Autolayout的编码而推出的抽象语言
3.语法
(1).语法列表

表达式 功能 v: 表示垂直 H: 表示水平 | 表示父控件的边框,前面是V:就代表垂直方向的父控件边框,前面是H:就代表水平方向的父控件边框,竖线前面没有V:和H:默认是水平方向,如 |[redView]表示redView紧贴父控件的左边框 - 表示一个小间隔或表示距离,如:V:|-20- 表示距离顶部20像素,|-[redView]表示redView距离父控件的左边框有一个小间隔 ( ) 括号里可以写控件名,如:H:|-[button1(button)]表示button1与button等宽;也可以写H:|-[button(==30)]表示button宽等于30像素 [] 方括号里表示写控件名,[button]表示button控件;H:[button1][button2]表示两个控件水平紧贴着 @value 表示优先级别,如: H:[button(>=50@800)] 表示button宽度大于等于50像素,该约束条件优先级为800(优先级最大值为1000,优先级越高的约束越先被满足)

(2).举例
H:[cancelButton(72)]-12-[acceptButton(50)]
canelButton宽72,acceptButton宽50,它们之间间距12

H:[wideView(>=60@700)]
wideView宽度大于等于60point,该约束条件优先级为700(优先级最大值为1000,优先级越高的约束越先被满足)

V:[redBox][yellowBox(==redBox)]
竖直方向上,先有一个redBox,其下方紧接一个高度等于redBox高度的yellowBox

H:|-10-[Find]-[FindNext]-[FindField(>=20)]-|
水平方向上,Find距离父view左边缘默认间隔宽度,之后是FindNext距离Find间隔默认宽度;再之后是宽度不小于20的FindField,它和FindNext以及父view右边缘的间距都是默认宽度。(竖线“|” 表示superview的边缘)
4.使用VFL语言设置约束的步骤
(1).用VFL语言创建VFL语句,用字符串表示
(2).把VFL语句中包含的数值或控件用字典表示

//创建一个字典(内部包含VFL语句中用到的控件)的快捷宏定义NSDictionary *dic = NSDictionaryOfVariableBindings(…);

(3).使用VFL来创建约束数组的常用方法

+ (NSArray *)constraintsWithVisualFormat:(NSString *)format                                  options:(NSLayoutFormatOptions)opts                                  metrics:(NSDictionary *)metrics                                    views:(NSDictionary *)views;/**解析 format :VFL语句   opts :约束类型,一般写kNilOptions,表示空选项metrics :VFL语句中用到的具体数值  views :VFL语句中用到的控件**/

(4).把约束数组添加到对应的控件中

- (void)addConstraints:(NSArray *)constraints;

5.代码举例

#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {  [super viewDidLoad];  //创建一个蓝色的View,不用设置Frame  UIView *blueView = [[UIView alloc] init];  blueView.backgroundColor = [UIColor blueColor];  //必须要设置为NO,默认是YES,在YES的时,系统会自动把Autoresizing的值转换成约束  blueView.translatesAutoresizingMaskIntoConstraints = NO;  [self.view addSubview: blueView];  //水平方向下:控件blueView的宽度等于100像素,左右边距为默认一个小间距  NSString *vfl1 = @"H:|-[blueView(==100)]-|";  NSDictionary *ditViews1 =  NSDictionaryOfVariableBindings(blueView);  NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:vfl1 options:kNilOptions metrics:nil views:ditViews1];  [self.view addConstraints:constraints];  //垂直方向下:控件blueView距左边距50个像素,高度等于100像素,右边距为默认一个小间距  NSNumber *n = @100;  NSString *vfl2 = @"V:|-50-[blueView(==n)]-|";  NSDictionary *metrics =  NSDictionaryOfVariableBindings(n);  NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:vfl2 options:kNilOptions metrics:metrics views:ditViews1];  [self.view addConstraints:constraints2];}@end

6.有用到Frmae属性的控件,不用把translatesAutoresizingMaskIntoConstraints属性设置为NO,设置为NO后,Frame将不起作用,值为0

#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {  [super viewDidLoad];  //创建一个蓝色的View  UIView *blueView = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 200, 200)];  blueView.backgroundColor = [UIColor blueColor];  //如果控件不设置约束,而是直接使用Frame,就不用设置属性为NO  blueView.translatesAutoresizingMaskIntoConstraints = YES;  [self.view addSubview: blueView];  //创建一个红色的View,不用设置Frame  UIView *redView = [[UIView alloc] init];  redView.backgroundColor = [UIColor redColor];  //必须要设置为NO,默认是YES,在YES的时,系统会自动把Autoresizing的值转换成约束  redView.translatesAutoresizingMaskIntoConstraints = NO;  [blueView addSubview:redView];  //redView与父控件的左右边距各为一个小间隔  NSString *vflH = @"|-[redView]-|";  NSDictionary *dic = NSDictionaryOfVariableBindings(redView);  NSArray *constraints1 = [NSLayoutConstraint constraintsWithVisualFormat:vflH options:kNilOptions metrics:nil views:dic];  [blueView addConstraints:constraints1];  //redView紧贴父控件的上边框,高度为100  NSString *vflV = @"V:|[redView(==100)]";  NSArray *constraints2 = [NSLayoutConstraint constraintsWithVisualFormat:vflV options:kNilOptions metrics:nil views:dic];  [blueView addConstraints:constraints2];}@end

七、Masonry
(一).简介
1.目前最流行的Autolayout第三方框架
2.用优雅的代码方式编写Autolayout
3.省去了苹果官方Autolayout长代码

(二).添加约束的类型
1.尺寸:width\height\size
2.边界:left\leading\right\trailing\top\bottom
3.中心点:center\centerX\centerY
4.边界:edges

(三).添加约束的方法
1.mas_makeConstraints:这个方法只会添加新的约束
2.mas_updateConstraints:这个方法将会覆盖以前的某些特定的约束
3.mas_remakeConstraints:这个方法会将以前的所有约束删掉,添加新的约束

(四).注意
1.创建的控件时不用再把控件的translatesAutoresizingMaskIntoConstraints属性设置为NO,框架里已经封装
2.equalTo方法不会对数据进行包装
3.mas_equalTo方法会对参数进行包装
4.multipliedBy表示乘数
5.offset:这个方法代表偏移量,正表示往下或往右移动,负表示往上或往左移动
6.当只对宽高进行约束,不对位置约束时,位置默认在父控件的左上角
7.只要添加了#define MAS_SHORTHAND这个宏,就不用带mas_前缀
8.只要添加了#define MAS_SHORTHAND_GLOBALS这个宏,equalTo就等价于mas_equalTo
9.#define MAS_SHORTHAND 和 #define MAS_SHORTHAND_GLOBALS 一定要添加到#import “Masonry.h”上面,因为Masonry.h里面的代码要用到这两个宏

(五).代码举例
下面代码中,每一个添加约束的方法都可以独立完整的添加约束,可以挨个进行测试

#import "ViewController.h"//define this constant if you want to use Masonry without the 'mas_' prefix#define MAS_SHORTHAND//define this constant if you want to enable auto-boxing for default syntax#define MAS_SHORTHAND_GLOBALS#import "Masonry.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {  [super viewDidLoad];  //创建一个红色视图  UIView *redView = [[UIView alloc] init];  redView.backgroundColor = [UIColor redColor];  [self.view addSubview:redView];  //mas_makeConstraints:这个方法只会添加新的约束  [redView mas_makeConstraints:^(MASConstraintMaker *make) {    //equalTo:这个方法不会对参数进行包装,    make.width.equalTo(@100);    //mas_equalTo:这个方法会对参数进行包装    make.width.mas_equalTo(100);    //offset:这个方法代表偏移量,正表示往下或往右移动,负表示往上或往右移动    make.top.equalTo(self.view).offset(100);    make.right.equalTo(self.view.mas_left).offset(200);  }];  //mas_updateConstraints:这个方法将会覆盖以前的某些特定的约束  [redView mas_updateConstraints:^(MASConstraintMaker *make) {    //size:设置宽和高的约束    make.size.equalTo([NSValue valueWithCGSize:CGSizeMake(50, 50)]);    //make.size.mas_equalTo(CGSizeMake(200 , 200));  }];  //mas_remakeConstraints:这个方法会将以前的所有约束删掉,添加新的约束  [redView mas_remakeConstraints:^(MASConstraintMaker *make) {    //redView高等于父控件的0.5倍,在加上10个像素    make.height.equalTo(self.view.mas_height).multipliedBy(0.5).offset(10);    //redView宽等于父控件的0.5倍,在减去10个像素    make.width.mas_equalTo(self.view.mas_width).multipliedBy(0.5).offset(-10);  }];  //mas_remakeConstraints:这个方法会将以前的所有约束删掉,添加新的约束  [redView mas_remakeConstraints:^(MASConstraintMaker *make) {    //距离父控件四周都是50间距    make.edges.mas_equalTo(self.view).insets(UIEdgeInsetsMake(50, 50, 50, 50));  }];  //mas_remakeConstraints:这个方法会将以前的所有约束删掉,添加新的约束  [redView mas_remakeConstraints:^(MASConstraintMaker *make) {    make.width.equalTo(@150);    make.height.mas_equalTo(150);    //redView的中心在父控件的中心    make.center.mas_equalTo(self.view).insets(UIEdgeInsetsZero);  }];  //mas_remakeConstraints:这个方法会将以前的所有约束删掉,添加新的约束  [redView mas_remakeConstraints:^(MASConstraintMaker *make) {    //必须要在文件开头添加 #define MAS_SHORTHAND 和 #define MAS_SHORTHAND_GLOBALS    //才能在equalTo中用基本数据类型的数据,宏定义会自动包装基本数据类型的数据    make.width.equalTo(100);    make.height.equalTo(100);    make.centerX.equalTo(self.view.centerX);    make.centerY.equalTo(self.view.centerY);  }];}@end
0 0
原创粉丝点击