本文主要是针对UIScrollView利用Masonry框架来自动布局,因为UIScrollView可以滑动,所以本身布局跟一般的UIView不太一样,然后楼主之前面试的时候也有人问过楼主这个问题,所以楼主想简单总结一下方便你我他它。关于Masonry这个框架,相信大家也都在用它,可以去github上面下载,它里面的各种demo也是非常有用的。 我们设置约束用到的几个方法简单介绍:一.mas_makeConstraints:设置约束,如果你的视图不需要根据什么情况更新约束,只需要设置一次的话,请使用它。
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.scrollView]; [self.scrollView addSubview:self.containerView]; [self.containerView addSubview:self.testButton]; [self.containerView addSubview:self.testView]; // 设置约束 [self setupConstraints]; } - (void)setupConstraints { [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(64); make.left.right.bottom.equalTo(self.view); }]; [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.scrollView); make.width.equalTo(self.scrollView); }]; [self.testButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(100); make.left.equalTo(self.containerView).offset(50); make.right.equalTo(self.containerView).offset(-50); make.height.equalTo(@40); }]; [self.testView mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.testButton.mas_bottom).offset(200); make.left.right.equalTo(self.containerView); make.height.equalTo(@400); make.bottom.equalTo(self.containerView); }]; } - (void)testButtonClick { [self setupConstraints]; }
第一次添加约束时,约束数组是酱紫的:
1.png
2..png
3.png
很明显,点击一次就会重复累加而不会清除之前的约束,后果可想而知。。。说到这里,大家应该理解mas_makeConstraints的使用场景了。 二.mas_updateConstraints:更新约束,如果你的布局需要根据具体情况来更新子控件的约束,那么请使用它。mas_updateConstraints是对比该对象之前的约束数组,添加过的约束就直接修改它的值,没有添加过的约束就添加上。
4.png
三.mas_remakeConstraints:在mas_makeConstraints的基础上会清除掉之前所有的约束,再重新添加新的约束。 UIScrollView的自动布局问题在利用自动布局来布局UIScrollView时,一般都会在上面添加一个UIView的子控件,来正确布局:
- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; [self.view addSubview:self.scrollView]; [self.scrollView addSubview:self.containerView]; [self.containerView addSubview:self.testButton]; [self.containerView addSubview:self.testView]; [self.view setNeedsUpdateConstraints]; } - (void)updateViewConstraints { [self.scrollView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.view).offset(64); make.left.right.bottom.equalTo(self.view); }]; [self.containerView mas_updateConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.scrollView); // 确定containerView的宽度 make.width.equalTo(self.scrollView); }]; [self.testButton mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(100); make.left.equalTo(self.containerView).offset(50); make.right.equalTo(self.containerView).offset(-50); make.height.equalTo(@40); }]; [self.testView mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.testButton.mas_bottom).offset(200); make.left.right.equalTo(self.containerView); make.height.equalTo(@400); // 确定containerView的高度 make.bottom.equalTo(self.containerView); }]; // 必须要调用 [super updateViewConstraints]; } scrollView的contentSize要根据containerView的高度来设置,containView的高度又要根据它内部的子控件来设置,make.bottom.equalTo(self.containerView)确定containerView的高度,make.width.equalTo(self.scrollView)确定containerview的宽度。 模拟复杂环境下UISCrollView的自动布局现假如有这么一种需求:一个控制器里面有多个视图A B C D,而每个视图的内容要去请求网络获取数据才能确定高度,但是对于这几个网络请求谁先成功获取数据计算到高度是不确定的,如何布局?
#pragma mark -- life cycle - (void)viewDidLoad { [super viewDidLoad]; self.oneHeight = 0; self.twoHeight = 0; self.threeHeight = 0; self.fourHeight = 0; [self.view addSubview:self.scrollView]; [self.scrollView addSubview:self.containerView]; [self.containerView addSubview:self.oneLabel]; [self.containerView addSubview:self.twoLabel]; [self.containerView addSubview:self.threeLabel]; [self.containerView addSubview:self.fourLabel]; [self.view setNeedsUpdateConstraints]; // 模拟3s后网络请求数据回来了,oneLabel根据数据获得了高度。 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.oneHeight = 80; [self.view setNeedsUpdateConstraints]; }); // 模拟6s后网络请求数据回来了,fourLabel根据数据获得了高度。 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.fourHeight = 100; [self.view setNeedsUpdateConstraints]; }); // 模拟9s后网络请求数据回来了,twoLabel根据数据获得了高度。 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(9 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.twoHeight = 150; [self.view setNeedsUpdateConstraints]; }); // 模拟12s后网络请求数据回来了,threeLabel根据数据获得了高度。 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(12 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ self.threeHeight = 60; [self.view setNeedsUpdateConstraints]; }); } - (void)updateViewConstraints { [self.scrollView mas_updateConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.view); }]; [self.containerView mas_updateConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(self.scrollView); make.width.equalTo(self.scrollView); }]; [self.oneLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.containerView).offset(50); make.left.right.equalTo(self.containerView); make.height.equalTo(@(self.oneHeight)); }]; [self.twoLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.oneLabel.mas_bottom); make.left.right.equalTo(self.containerView); make.height.equalTo(@(self.twoHeight)); }]; [self.threeLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.twoLabel.mas_bottom); make.left.right.equalTo(self.containerView); make.height.equalTo(@(self.threeHeight)); }]; [self.fourLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.threeLabel.mas_bottom); make.left.right.equalTo(self.containerView); make.height.equalTo(@(self.fourHeight)); make.bottom.equalTo(self.containerView); }]; [super updateViewConstraints]; }
(责任编辑:好模板) |