Auto Layout Process 自动布局过程
2016-03-26 11:42
274 查看
用Masonry实现改变约束,动画功能,需要用到自动布局的几个方法,研究了下自动布局的过程方法
1、setNeedsUpdateConstraints
当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用
2、needsUpdateConstraints
constraint-based layout system使用此返回值去决定是否需要调用
3.updateConstraintsIfNeeded
立即触发约束更新,自动更新布局。
4、updateConstraints
自定义view应该重写此方法在其中建立constraints. 注意:要在实现在最后调用
第一步:updating constraints,被称为测量阶段,其从下向上(from subview to super view),为下一步layout准备信息。可以通过调用方法
自定义view的话,通常可以重写updateConstraints方法,在其中可以添加view需要的局部的contraints。
第二步:layout,其从上向下(from super view to subview),此步主要应用上一步的信息去设置view的center和bounds。可以通过调用setNeedsLayout去触发此步骤,此方法不会立即应用layout。如果想要系统立即的更新layout,可以调用layoutIfNeeded。另外,自定义view可以重写方法layoutSubViews来在layout的工程中得到更多的定制化效果。
第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发,
因为每一步都依赖前一步,因此一个display可能会触发layout,当有任何layout没有被处理的时候,同理,layout可能会触发updating constraints,当constraint system更新改变的时候。
需要注意的是,这三步不是单向的,constraint-based layout是一个迭代的过程,layout过程中,可能去改变constraints,有一次触发updating constraints,进行一轮layout过程。
注意:如果你每一次调用自定义layoutSubviews都会导致另一个布局传递,那么你将会陷入一个无限循环中
//
// ViewController.m
// MasnoryDemo
//
// Created by 帝炎魔 on 16/3/25.
// Copyright © 2016年 帝炎魔. All rights reserved.
//
#import "ViewController.h"
#import "MyView.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *movingButton;
@property (nonatomic, assign) BOOL topLeft;
@end
@implementation ViewController
-(void)loadView
{
[super loadView];
MyView *myView = [[MyView alloc] init];
// 初始化按钮
_movingButton = myView.button;
[self.view addSubview:_movingButton];
}
- (void)viewDidLoad {
[super viewDidLoad];
[_movingButton setTitle:@"点击" forState:UIControlStateNormal];
_movingButton.layer.borderColor = UIColor.greenColor.CGColor;
_movingButton.layer.borderWidth = 3;
[_movingButton addTarget:self action:@selector(clickWithButton:) forControlEvents:UIControlEventTouchUpInside];
self.topLeft = YES;
[self.view setNeedsUpdateConstraints];
}
- (void)updateViewConstraints {
// 重置约束 会把已有的约束删除重新添加
[self.movingButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(100));
make.height.equalTo(@(100));
// 判断当前button位置
if (self.topLeft) {
make.left.equalTo(self.view).offset(10);
make.top.equalTo(self.view).offset(10);
}
else {
make.bottom.equalTo(self.view).offset(-10);
make.right.equalTo(self.view).offset(-10);
}
}];
[super updateViewConstraints];
}
- (void)clickWithButton:(UIButton *)button
{
self.topLeft = !self.topLeft;
// 执行updateViewConstraints 重新给约束
[self.view setNeedsUpdateConstraints];
// 立即触发约束更新, 自动更新布局
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.4 animations:^{
[self.view layoutIfNeeded];
}];
}
@end
1、setNeedsUpdateConstraints
当一个自定义view的某个属性发生改变,并且可能影响到constraint时,需要调用此方法去标记constraints需要在未来的某个点更新,系统然后调用
updateConstraints.
2、needsUpdateConstraints
constraint-based layout system使用此返回值去决定是否需要调用
updateConstraints作为正常布局过程的一部分。
3.updateConstraintsIfNeeded
立即触发约束更新,自动更新布局。
4、updateConstraints
自定义view应该重写此方法在其中建立constraints. 注意:要在实现在最后调用
[super updateConstraints]
Auto Layout Process 自动布局过程
与使用springs and struts(autoresizingMask)比较,Auto layout在view显示之前,多引入了两个步骤:updating constraints 和laying out views。每一个步骤都依赖于上一个。display依赖layout,而layout依赖updating constraints。updating constraints->layout->display
第一步:updating constraints,被称为测量阶段,其从下向上(from subview to super view),为下一步layout准备信息。可以通过调用方法
setNeedUpdateConstraints去触发此步。constraints的改变也会自动的触发此步。但是,当你自定义view的时候,如果一些改变可能会影响到布局的时候,通常需要自己去通知Auto layout,updateConstraintsIfNeeded。
自定义view的话,通常可以重写updateConstraints方法,在其中可以添加view需要的局部的contraints。
第二步:layout,其从上向下(from super view to subview),此步主要应用上一步的信息去设置view的center和bounds。可以通过调用setNeedsLayout去触发此步骤,此方法不会立即应用layout。如果想要系统立即的更新layout,可以调用layoutIfNeeded。另外,自定义view可以重写方法layoutSubViews来在layout的工程中得到更多的定制化效果。
第三步:display,此步时把view渲染到屏幕上,它与你是否使用Auto layout无关,其操作是从上向下(from super view to subview),通过调用setNeedsDisplay触发,
因为每一步都依赖前一步,因此一个display可能会触发layout,当有任何layout没有被处理的时候,同理,layout可能会触发updating constraints,当constraint system更新改变的时候。
需要注意的是,这三步不是单向的,constraint-based layout是一个迭代的过程,layout过程中,可能去改变constraints,有一次触发updating constraints,进行一轮layout过程。
注意:如果你每一次调用自定义layoutSubviews都会导致另一个布局传递,那么你将会陷入一个无限循环中
//
// ViewController.m
// MasnoryDemo
//
// Created by 帝炎魔 on 16/3/25.
// Copyright © 2016年 帝炎魔. All rights reserved.
//
#import "ViewController.h"
#import "MyView.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *movingButton;
@property (nonatomic, assign) BOOL topLeft;
@end
@implementation ViewController
-(void)loadView
{
[super loadView];
MyView *myView = [[MyView alloc] init];
// 初始化按钮
_movingButton = myView.button;
[self.view addSubview:_movingButton];
}
- (void)viewDidLoad {
[super viewDidLoad];
[_movingButton setTitle:@"点击" forState:UIControlStateNormal];
_movingButton.layer.borderColor = UIColor.greenColor.CGColor;
_movingButton.layer.borderWidth = 3;
[_movingButton addTarget:self action:@selector(clickWithButton:) forControlEvents:UIControlEventTouchUpInside];
self.topLeft = YES;
[self.view setNeedsUpdateConstraints];
}
- (void)updateViewConstraints {
// 重置约束 会把已有的约束删除重新添加
[self.movingButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(@(100));
make.height.equalTo(@(100));
// 判断当前button位置
if (self.topLeft) {
make.left.equalTo(self.view).offset(10);
make.top.equalTo(self.view).offset(10);
}
else {
make.bottom.equalTo(self.view).offset(-10);
make.right.equalTo(self.view).offset(-10);
}
}];
[super updateViewConstraints];
}
- (void)clickWithButton:(UIButton *)button
{
self.topLeft = !self.topLeft;
// 执行updateViewConstraints 重新给约束
[self.view setNeedsUpdateConstraints];
// 立即触发约束更新, 自动更新布局
[self.view updateConstraintsIfNeeded];
[UIView animateWithDuration:0.4 animations:^{
[self.view layoutIfNeeded];
}];
}
@end
相关文章推荐
- 第二章 Java基础之GJLIB动态代理
- Spring AOP编程
- error C2664: “strcpy”: 不能将参数 2 从“CString”转换为“const char *”
- 51nod1428 活动安排问题
- Java String常见面试题汇总
- MFC中POSITION类详解
- 2016阿里云实习面经
- Android Studio 安装教程
- UITabBarController 根视图控制器
- 关于音频PCM数据2字节(16位)byte与64位double之间的转换
- ZooKeeper Watch Java API浅析exists
- Android APK反编译
- Android LocalActivityManager的用法
- 由一个bug引发的SQLite缓存一致性探索
- Eclipse下的Setting property 'source' to '...' did not find a matching property 错误
- valgrind
- 集合第二发Set接口
- Java中将JSON格式的数据转换成对应的Bean、Map、List数据
- Hibernate的findByExample莫名加入了值为空的的属性做查询条件
- winform程序生成条形码并且并且保存到本地文件中。