一、苹果产品的发行
机型 | 预装系统 | 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 |
三、屏幕适配
- iPhone4S之前没有屏幕适配,因为屏幕尺寸不变,全部用frame、bounds、center进行布局。
- iphone5之后才开始有屏幕适配。
四、Autoresizing
- iPad的出现和iPhone横屏的出现,出现Autoresizing技术
- Autoresizing让横竖屏适配相对于用frame、bounds、center进行布局简单
- 使用Autoresizing的前提是:关闭Autolayout功能;因为有些功能重复
- 局限性
- 只能解决子控件跟父控件的相对关系问题
- 不能解决兄弟控件的相对关系问题 - 当控件的的autoresizesSubviews是YES时,(默认是YES),那么UIView对象的子控件会根据子控件自身的autoresizingMask属性值来自动适应与其父控件之间的位置和大小
- storyboard或xib下使用Autoresizing,宽高和宽度的自动调整:实线代表选中,左右上下间距的自动调整:虚线代表选中
- 纯代码使用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