前言
IOS自动布局有sb、xib自适应或者是纯代码编写frame布局,前者本人不太喜欢,后者计算太多也是比较繁琐,masonry这个第三方库,其实是封装了autolayout的约束,易于我们使用纯代码编写自适应布局。
(一)下面的这个例子是一个绑定手机号成功的页面布局;
#import "BindSuccessViewController.h"
#import <Masonry.h>
#define SCREEN_WIDTH CGRectGetWidth([UIScreen mainScreen].bounds)
@interface BindSuccessViewController () {
UIImageView *imageView;
UILabel *alertlabel;
UIImageView *hfImageView;
UIButton *sureButton;
UIButton *cancelButton;
UIScrollView *scrollView;
UIView *layoutView;
}
@end
@implementation BindSuccessViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"修改手机号";
self.view.backgroundColor = [UIColor whiteColor];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStylePlain target:self action:@selector(clickCancelButton)];
[self initView];
[self configView];
}
- (void)initView {
scrollView = [UIScrollView new];
scrollView.bounces = NO;
scrollView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:scrollView];
layoutView = [UIView new];
layoutView.backgroundColor = [UIColor whiteColor];
[scrollView addSubview:layoutView];
imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"success"];
[layoutView addSubview:imageView];
alertlabel = [UILabel new];
alertlabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 30;
alertlabel.numberOfLines = 0;
alertlabel.text = @"您已经成功的修改手机号!";
alertlabel.font = [UIFont systemFontOfSize:14.0f];
alertlabel.textAlignment = NSTextAlignmentCenter;
[layoutView addSubview:alertlabel];
hfImageView = [UIImageView new];
hfImageView.image = [UIImage imageNamed:@"setting-hf"];
[layoutView addSubview:hfImageView];
sureButton = [UIButton buttonWithType:UIButtonTypeCustom];
sureButton.backgroundColor = [UIColor colorWithRed:0 green:160.0f/255 blue:223.0f/255 alpha:1.0f];
[sureButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[sureButton setTitle:@"确定" forState:UIControlStateNormal];
[sureButton addTarget:self action:@selector(clickSureButton) forControlEvents:UIControlEventTouchUpInside];
[layoutView addSubview:sureButton];
cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.layer.borderWidth = 1.0f;
cancelButton.layer.borderColor = [UIColor colorWithRed:0 green:160.0f/255 blue:223.0f/255 alpha:1.0f].CGColor;
[cancelButton setTitle:@"取消" forState:UIControlStateNormal];
[cancelButton setTitleColor:[UIColor colorWithRed:0 green:160.0f/255 blue:223.0f/255 alpha:1.0f] forState:UIControlStateNormal];
[cancelButton addTarget:self action:@selector(clickCancelButton) forControlEvents:UIControlEventTouchUpInside];
[layoutView addSubview:cancelButton];
}
- (void)configView {
[scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
[layoutView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.mas_equalTo(0);
make.width.mas_equalTo(self.view);
make.bottom.equalTo(cancelButton.mas_bottom).offset(20);
}];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(layoutView).offset(20);
make.centerX.equalTo(scrollView);
make.width.mas_equalTo(@60);
make.height.mas_equalTo(@60);
}];
[alertlabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(imageView.mas_bottom).offset(15);
make.left.equalTo(layoutView).offset(15);
make.right.equalTo(layoutView).offset(-15);
}];
[hfImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(alertlabel.mas_bottom).offset(30);
make.centerX.equalTo(scrollView);
make.width.mas_equalTo(@277);
make.height.mas_equalTo(@165);
}];
[sureButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(hfImageView.mas_bottom).offset(20);
make.left.equalTo(layoutView).offset(15);
make.right.equalTo(layoutView).offset(-15);
make.height.mas_equalTo(@40);
}];
[cancelButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(sureButton.mas_bottom).offset(20);
make.left.equalTo(sureButton);
make.right.equalTo(sureButton);
make.height.mas_equalTo(@40);
}];
[scrollView mas_updateConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(layoutView.mas_bottom).priorityLow();
make.bottom.mas_greaterThanOrEqualTo(self.view);
}];
}
- (void)clickSureButton
{
}
- (void)clickCancelButton
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
@end
解释一下一段,使得cancelButton始终会离底部有一段距离,[scrollView mas_updateConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(layoutView.mas_bottom).priorityLow();
make.bottom.mas_greaterThanOrEqualTo(self.view);
}]; 这段约束的意思是,先设置了scrollview的bottom等于layoutView的底部+20,但是它的优先级最低,然后又设置了scrollview的bottom大于或等于self.view,也就是说scrollview的contentSize.height至少等于屏幕高度。
总结
uiscrollview是一个比较特殊的视图,使用自适应布局的话contentsize的大小取决于subviews,所以在布局时要特别的注意,不然会出现约束冲突。网络上看到一个布局原则:整体frame布局,局部masonry自适应布局。