AutoLayout -Masonry

History and Something Insteresting

手写代码的UI的自动布局在iOS6中引入的新特性iOS 6 brings an awesome new feature to the iPhone and iPad: Auto Layout, 以取代之前的 autoresizingMask( “springs and struts” Model).

实际上关于纯手写代码UI Layout经历了三个时期,固定宽高(这个用frame设计非常容易),AutoresizingMask以及最新的Autolayout. 由于iphone6/6S发布后,苹果手机屏幕尺寸呈现多样性,所以Autolayout为APP开发提供了便捷的UI布局方案。

Masonry是一个轻量级的Layout框架,采用更自然的链式语法封装autolayout,同时支持iOS和Mac OS X.
Auto Layout 已经集成到Xcode5 + 版本的开发环境中,新建项目将默认开启Auto Layout.

Usage

  • Step1 将Masonry库添加到工程中
//编辑Podfile文件,添加(可以使用 pod search masonry 查询最新支持版本)
pod 'Masonry', '~> 0.6.0'

//然后, 在 Terminate 中输入如下命令
pod install
//或者
pod update
  • Step2 在程序文件中使用masonry对视图对象设置约束
//导入头文件:
#import <Masonry/Masonry.h>

// 在Cell中,对属性topBarrier设置Constraints, self.contentView是其父视图
// **注意 equalTo(<对象约束属性>), mas_equalTo(<Value值>)**
// 具体的一些属性含义,可以参加参考文献第一篇
[self.topBarrier mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.contentView).offset(5);
        make.left.equalTo(self.contentView.mas_left);
        make.width.equalTo(self.contentView.mas_width);
        make.height.mas_equalTo(@10);
}];


  • Step3 进阶:Masonry创建constraint定义Layout的三种方式
//1. mas_makeConstraints
// 为某个视图对象创建constraint,可以通过设置变量或属性来保存Constraint,并重复利用
// 如 picturesViewTop 这个MASConstraint 类型变量存储了constraint,下次可以复用
[self.picturesView mas_makeConstraints:^(MASConstraintMaker *make) {
       MASConstraint *picturesViewTop = make.top.equalTo(self.topBarrier.mas_bottom).offset(5);
       make.left.equalTo(self.topBarrier.mas_left);
       make.height.equalTo(@(self.pictureHeight));
       make.width.equalTo(@(self.pictureWidth));
}];

//2. mas_updateConstraints
// 更新某个视图对象的constraint,而非创建固定constraint
// 下面模拟使用场景
// 重写系统即 UIConstraintBasedLayoutCoreMethods 的 updateConstraints 方法
- (void)updateConstraints
{
    [self.pictureView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@(self.pictureHeight));
        make.width.equalTo(@(self.pictureWidth));
    }];
    [super updateConstraints];
}
// 目的是通过高度和宽度属性(self.pictureHeight,self.pictureWidth)的变化来实现Constraints更新
// 在需要更新的地方添加如下代码, 则会更新相应约束,冲突的Constraints 以更新中的Constraints为准
self.pictureHeight100;
self.pictureWidth100;
[self setNeedsUpdateConstraints];
[self updateConstraints];

// 3. mas_remakeConstraints
// 和mas_updateConstraints 相似,都是更新Constraints,不同的是 mas_remakeConstraints 会删除之前的Constraints, 然后以新的Constraints 为准。

Important Methods for AutoLayout

  • 方法列表
Methods Function Usage
setNeedsUpdateConstraints 设置View需要更新约束
下次计算或者更新约束时会更新
在需要更新约束的时候调用
确保系统需要更新状态
updateConstraintsIfNeeded 立即触发约束更新,如果有约束要更新 系统调用 updateConstraints 方法
实现约束更新
setNeedsLayout 设置View页面需要更新,但不立即执行 在需要更新页面布局时调用
layoutIfNeeded 立即触发页面布局更新 系统重写布局时调用layoutSubviews 方法
  • 方法总结

setNeedsUpdateConstraints 方法确保系统需要更新约束,系统再调用 updateConstraintsIfNeeded 时能确定调用 updateConstraints 达到立即更新约束的目的。如果不调用 setNeedsUpdateConstraints 且在View上没有约束变化,则系统不会调用 updateConstraints
setNeedsLayout 和上述类似原理。
需要注意的是: 系统调用layoutSubviews时会调用updateConstraintsIfNeeded,通过更新约束,从superView 到 subView的层次顺序来计算frame,反向确定布局。

  • Auto Layout Process (自动布局流程)
Step 1 Update Constraints 布局的测量阶段,通过 setNeedsUpdateConstraints 触发 Step 2 layout 通过Step 1 的信息去设置View的 Center和Bounds,自上而下(from super view to subview)通过setNeedsLayout 触发 Step 3 display 把View渲染到屏幕,操作也是自上而下,通过 setNeedsDisplay触发 由于他们有依赖关系,即 update Constraints -> layout -> display, 因此 display 可能触发 layout, layout 可能触发 update Constraints 

Issues

问题描述: 使用UITableView+FDTemplateLayoutCell实现Cell高度自适应计算,但在Cell中用Masonry定义的约束不严谨,即没有形成闭环,例如 最后约束的bottom没有加,则masonry计算布局出错,呈现的效果就是叠影。

// tableViewCell中定义的Masonry
    [self.commentBarrier mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.elfretweetedBackground.mas_bottom);
        make.width.equalTo(self.contentView.mas_width);
        make.height.mas_equalTo(0.5);
    }];
    [self.commentBar mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.commentbarrier.mas_bottom).offset(5);
        make.width.equalTo(self.contentView.mas_width);
        make.height.mas_equalTo(25);
        // ****** 注意约束闭环 ******
        make.bottom.equalTo(self.contentView.mas_bottom);
    }];

// TableViewController 中的TableView代理方法
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 使用 UITableView+FDTemplateLayoutCell
    return [tableView fd_heightForCellWithIdentifier:@"cellIdentifier" cacheByIndexPath:indexPath configuration:^(WeiBoContentTableViewCell *cell) {
    // cell 类型
        WeiBoDataStatus *status = self.statuses[indexPath.section][indexPath.row];
        [cell setupStatus:status];
    }];
}

References

masonry github

Masonry介绍与使用实践(快速上手Autolayout)

Beginning Auto Layout Tutorial in iOS 7: Part 1

Auto Layout Guide

iOS中AutoLayer自动布局流程及相关方法

AutoLayout:浅析动画

先进的自动布局工具箱

你可能感兴趣的:(ios,masonry,autolayout)