MagicNumber -> autoresizingMask -> autolayout
以上是纯手写代码所经历的关于页面布局的三个时期;
在iphone1 ~ iphone3gs
时代,window的size固定为(320, 480), 我们只需要简单计算一下相对位置就好了。
在iphone4 ~ iphone4s
时代,苹果推出了retina屏,但是给了码农们非常大的福利:window的size不变。
在iphone5 ~ iphone5s
时代,window的size变了(320, 568) 这时autoresizingMask
派上了用场,简单的适配一下即可。 此时没用autolayout
是由于要适配iOS5。
在iphone6+
时代,window的width也发生了变化(相对5和5s的屏幕比例没有变化), 终于是时候抛弃autoresizingMask
改用auto layout
了,此时,不用支持iOS5了,相对于屏幕适配的多样性来说autoresizingMask
也已经过时了)。
那如何快速的上手autolayout呢?在我刚接触iOS的时候,还在用系统的自动布局,但是系统自动布局过于繁琐,如下创建一个黑色视图,距离屏幕上方20像素,左、右以及下方距离屏幕各10个像素,代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view = [[UIView alloc] init];
// 系统自动布局必需将 translatesAutoresizingMaskIntoConstraints 属性置为 NO
view.translatesAutoresizingMaskIntoConstraints = NO;
view.backgroundColor = [UIColor blackColor];
[self.view addSubview:view];
// 添加约束
// 水平约束
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[view]-10-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(view)]];
// 垂直约束
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[view]-10-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(view)]];
}
Masonry
三方布局框架,使得布局更加简单易用,这将是我分享Masonry
三方布局的目的,望有幸与各位大神共同探讨。Masonry
是一个轻量级的布局框架,拥有自己的描述语法,采用优雅的链式语法封装自动布局,简洁明了,可读性高,而且同时支持iOS
和Max OS X
。
Masonry
是一个用代码写iOS
或OS
界面的库,可以代替Auto layout
。
Masonry
布局,无需将属性translatesAutoresizingMaskIntoConstraints
置为NO
,因为Masonry
已经帮我们执行了这一步。
@property (nonatomic, strong, readonly) MASConstraint *left; /**< 左侧 */
@property (nonatomic, strong, readonly) MASConstraint *top; /**< 顶部 */
@property (nonatomic, strong, readonly) MASConstraint *right; /**< 右侧 */
@property (nonatomic, strong, readonly) MASConstraint *bottom; /**< 底部 */
@property (nonatomic, strong, readonly) MASConstraint *leading; /**< 首部 */
@property (nonatomic, strong, readonly) MASConstraint *trailing; /**< 尾部 */
@property (nonatomic, strong, readonly) MASConstraint *width; /**< 宽度 */
@property (nonatomic, strong, readonly) MASConstraint *height; /**< 高度 */
@property (nonatomic, strong, readonly) MASConstraint *centerX; /**< 中心点X */
@property (nonatomic, strong, readonly) MASConstraint *centerY; /**< 中心点Y */
@property (nonatomic, strong, readonly) MASConstraint *baseline; /**< 文本基线 */
github地址:https://github.com/SnapKit/Masonry
安装后导入头文件:#import "Masonry.h"
pod ‘Masonry’, ‘~> 0.6.2’
安装后导入头文件:#import <Masonry.h>
mas_makeConstraints
是给view
添加约束,约束有几种,分别是边距,宽,高,左上右下距离,基准线。添加过约束后可以有修正,修正有offset
(位移)修正和multipliedBy
(倍率)修正。
语法一般是make.equalTo or make.greaterThanOrEqualTo or make.lessThanOrEqualTo
+ 倍数和位移修正。
- (void)viewDidLoad {
[super viewDidLoad];
// 使用 Masonry 布局,基本可以抛弃 CGRectMake 了,直接初始化即可。
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor darkGrayColor];
// 在做布局之前,一定要先将 view 添加到 superview 上,否则会报错。
[self.view addSubview:view];
// mas_makeConstraints 就是 Masonry 的 autolayout 添加函数,将所需的约束添加到block中就行。
[view mas_makeConstraints:^(MASConstraintMaker *make) {
// 设置居中
make.center.equalTo(self.view);
// 设置宽度为200
make.width.equalTo(@200);
// 设置高度为200
make.height.mas_equalTo(200);
}];
}
1、使用mas_makeConstraints
方法的元素必须事先添加到父元素的中,例如:[self.view addSubview:view];
2、mas_equalTo
和equalTo
区别:mas_equalTo
比equalTo
多了类型转换操作,一般来说,大多数时候两个方法都是通用的,但是对于数值元素
使用mas_equalTo
。对于对象或是多个属性的处理,使用equalTo
。特别是多个属性时,必须使用equalTo
,例如:make.left.and.right.equalTo(self.view);
。
3、注意方法with
和and
,这两个方法其实没有做任何操作,方法只是返回对象本身,这个方法的左右完全是为了方法写的时候的可读性 ,如下两行代码是完全一样的,但是明显加了and
方法的语句可读 性更高点。
make.left.and.right.equalTo(self.view);
make.left.right.equalTo(self.view);
加载一个上边距为20,下、左、右边距为10的黑色视图。
代码展示:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *blackView = [[UIView alloc] init];
blackView = [UIColor blackColor];
[self.view addSubview:blackView];
[blackView mas_makeConstraints:^(MASConstraintMaker *make) {
// 方法1:
// make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(20, 10, 10, 10));
// 方法2:
// make.top.left.bottom.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(20, 10, 10, 10));
// 方法3:
// 设置其左侧和父视图偏移10个像素
make.left.equalTo(self.view).with.offset(10);
// 设置其右侧和父视图偏移10个像素
make.right.equalTo(self.view).with.offset(-10);
// 设置其顶部和父视图偏移20个像素
make.top.equalTo(self.view).with.offset(20);
// 设置其尾部和父视图偏移10个像素
make.bottom.equalTo(self.view).with.offset(-10);
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 黑色视图
UIView *blackView = [[UIView alloc] init];
blackView.backgroundColor = [UIColor blackColor];
[self.view addSubview:blackView];
[blackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(20, 10, 10, 10));
}];
// 棕色视图
UIView *brownView = [[UIView alloc] init];
brownView.backgroundColor = [UIColor brownColor];
[blackView addSubview:brownView];
[brownView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设置其中心点为父视图的中心点
make.center.mas_equalTo(blackView);
// 设置其宽度为父视图的宽度
make.width.mas_equalTo(blackView);
// 设置其高度为300
make.height.mas_equalTo(300);
}];
}
在棕色视图中并排显示红色视图、紫色视图,红色视图左侧距离父视图20像素,紫色视图右侧距离父视图20像素,紫色视图与红色视图等高,等宽。
代码展示:
- (void)viewDidLoad {
[super viewDidLoad];
// 黑色视图
UIView *blackView = [[UIView alloc] init];
blackView.backgroundColor = [UIColor blackColor];
[self.view addSubview:blackView];
[blackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(20, 10, 10, 10));
}];
// 棕色视图
UIView *brownView = [[UIView alloc] init];
brownView.backgroundColor = [UIColor brownColor];
[blackView addSubview:brownView];
[brownView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设置其中心点为父视图的中心点
make.center.mas_equalTo(blackView);
// 设置其宽度为父视图的宽度
make.width.mas_equalTo(blackView);
// 设置其高度为300
make.height.mas_equalTo(300);
}];
// 红色视图
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
[brownView addSubview:redView];
// 紫色视图
UIView *purpleView = [[UIView alloc] init];
purpleView.backgroundColor = [UIColor purpleColor];
[brownView addSubview:purpleView];
// 布局红色视图、紫色视图
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
// 设置其位于父视图的Y轴的中心位置
make.centerY.mas_equalTo(brownView);
// 设置其左侧与父视图偏移20像素
make.left.mas_equalTo(brownView).offset(20);
// 设置其高度为260
make.height.mas_equalTo(260);
// 设置其宽度与紫色视图等宽
make.width.mas_equalTo(purpleView);
}];
[purpleView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(brownView.mas_centerY);
make.left.equalTo(redView.mas_right).with.offset(20);
make.right.equalTo(brownView.mas_right).with.offset(-20);
make.height.mas_equalTo(redView);
make.width.equalTo(redView);
}];
}
注意下面设置宽度的时候是传递的数组,这样才能让多个视图进行等距离显示。
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化视图
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 greenColor];
[self.view addSubview:view3];
// 布局视图
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
// 设置中心点
make.centerY.mas_equalTo(self.view);
// 设置左侧距离父视图10像素
make.left.equalTo(self.view).offset(10);
// 设置右侧距离和view2的左侧相距10像素
make.right.equalTo(view2.mas_left).offset(-10);
// 设置高度
make.height.mas_equalTo(200);
// 设置宽度和view2以及view3相等
make.width.equalTo(@[view2, view3]);
}];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.view);
make.height.mas_equalTo(view1);
make.width.equalTo(@[view1, view3]);
}];
[view3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(self.view);
make.left.equalTo(view2.mas_right).offset(10);
make.right.equalTo(self.view).offset(-10);
make.height.mas_equalTo(view1);
make.width.equalTo(@[view1, view2]);
}];
}