自动布局最重要的是约束:UI元素间关系的数学表达式。约束包括尺寸、由优先级和阈值管理的相对位置。它们是添加剂,可能导致约束冲突 、约束不足造成布局无法确定 。这两种情况都会产生异常。

使用前:AutoLayout关于更新的几个方法的区别

  • setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
  • layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。
  • layoutSubviews:系统重写布局
  • setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始
  • updateConstraintsIfNeeded:告知立刻更新约束
  • updateConstraints:系统更新约束

使用

1. 基本使用

  • mas_makeConstraints:添加约束
  • mas_updateConstraints:更新约束、亦可添加新约束
  • mas_remakeConstraints:重置之前的约束

  • multipler属性表示约束值为约束对象的乘因数, dividedBy属性表示约束值为约束对象的除因数,可用于设置view的宽高比

// 进行屏幕的适配的时候,往往需要根据屏幕宽度来适配一个相应的高度,在此推荐使用如下约束的方式来进行控件的适配
    [self.topView addSubview:self.topInnerView];
    [self.topInnerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(self.topView.mas_height).dividedBy(3);
        make.width.and.height.lessThanOrEqualTo(self.topView);
        make.width.and.height.equalTo(self.topView).with.priorityLow();
        make.center.equalTo(self.topView);
    }];

  • priorityLow()设置约束优先级
  • #define MAS_SHORTHAND_GLOBALS使用全局宏定义,可以使equalTo等效于mas_equalTo
  • #define MAS_SHORTHAND使用全局宏定义, 可以在调用masonry方法的时候不使用mas_前缀
  1. // 这里注意到一个地方,就是当使用了这个全局宏定义之后,发现可以有个类`NSArray+MASAdditions.h`,看了之后发现可以
  2. self.buttonViews = @[ raiseButton, lowerButton, centerButton ];
  3. // 之后可以在updateConstraints 方法中
  4. - (void)updateConstraints {
  5. [self.buttonViews updateConstraints:^(MASConstraintMaker *make) {
  6. make.baseline.equalTo(self.mas_centerY).with.offset(self.offset);
  7. }];
  8. [super updateConstraints];
  9. }

动态修改视图约束:

  1. // 创建视图约束
  2. [blueView mas_makeConstraints:^(MASConstraintMaker *make) {
  3. self.animatableConstraint = make.edges.equalTo(superview).insets(paddingInsets).priorityLow();
  4. ]];
  5. // 更改约束 (另一处方法中)
  6. UIEdgeInsets paddingInsets = UIEdgeInsetsMake(padding, padding, padding, padding);
  7. self.animatableConstraint.insets = paddingInsets
  8. [self layoutIfNeeded];
  • debug模式:

    1. // 对某个view添加key值
    2. greenView.mas_key = @"greenView";
    3. // 或者如下顺序
    4. MASAttachKeys(greenView, redView, blueView, superview);
    5. // 同样的对每条约束亦可以添加key
    6. make.height.greaterThanOrEqualTo(@5000).key(@"ConstantConstraint");
  • preferredMaxLayoutWidth: 多行label的约束问题
  1. // 已经确认好了位置
  2. // 在layoutSubviews中确认label的preferredMaxLayoutWidth值
  3. - (void)layoutSubviews {
  4. [super layoutSubviews];
  5. // 你必须在 [super layoutSubviews] 调用之后,longLabel的frame有值之后设置preferredMaxLayoutWidth
  6. self.longLabel.preferredMaxLayoutWidth = self.frame.size.width-100;
  7. // 设置preferredLayoutWidth后,需要重新布局
  8. [super layoutSubviews];
  9. }
  • scrollView使用约束的问题:原理通过一个contentView来约束scrollView的contentSize大小,也就是说以子控件的约束条件,来控制父视图的大小
  1. // 1. 控制scrollView大小(显示区域)
  2. [self.scrollView makeConstraints:^(MASConstraintMaker *make) {
  3. make.edges.equalTo(self.view);
  4. }];
  5. // 2. 添加一个contentView到scrollView,并且添加好约束条件
  6. [contentView makeConstraints:^(MASConstraintMaker *make) {
  7. make.edges.equalTo(self.scrollView);
  8. // 注意到此处的宽度约束条件,这个宽度的约束条件是比添加项
  9. make.width.equalTo(self.scrollView);
  10. }];
  11. // 3. 对contentView的子控件做好约束,达到可以控制contentView的大小
  • 新方法:2个或2个以上的控件等间隔排序
  1. /**
  2. * 多个控件固定间隔的等间隔排列,变化的是控件的长度或者宽度值
  3. *
  4. * @param axisType 轴线方向
  5. * @param fixedSpacing 间隔大小
  6. * @param leadSpacing 头部间隔
  7. * @param tailSpacing 尾部间隔
  8. */
  9. - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
  10. withFixedSpacing:(CGFloat)fixedSpacing l
  11. eadSpacing:(CGFloat)leadSpacing
  12. tailSpacing:(CGFloat)tailSpacing;
  13. /**
  14. * 多个固定大小的控件的等间隔排列,变化的是间隔的空隙
  15. *
  16. * @param axisType 轴线方向
  17. * @param fixedItemLength 每个控件的固定长度或者宽度值
  18. * @param leadSpacing 头部间隔
  19. * @param tailSpacing 尾部间隔
  20. */
  21. - (void)mas_distributeViewsAlongAxis:(MASAxisType)axisType
  22. withFixedItemLength:(CGFloat)fixedItemLength
  23. leadSpacing:(CGFloat)leadSpacing
  24. tailSpacing:(CGFloat)tailSpacing;

使用方法很简单,因为它是NSArray的类扩展:

  1. // 创建水平排列图标 arr中放置了2个或连个以上的初始化后的控件
  2. // alongAxis 轴线方向 固定间隔 头部间隔 尾部间隔
  3. [arr mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:20 leadSpacing:5 tailSpacing:5];
  4. [arr makeConstraints:^(MASConstraintMaker *make) {
  5. make.top.equalTo(@60);
  6. make.height.equalTo(@60);
  7. }];

2. 注意事项

  • 约束视图对象只有在被addSubview之后,才能给视图添加约束
  • 当你的所有约束都在 updateConstraints 内调用的时候,你就需要在此调用此方法,因为 updateConstraints方法是需要触发的
  1. // 调用在view 内部,而不是viewcontroller
  2. + (BOOL)requiresConstraintBasedLayout {
  3. return YES;
  4. }
  5. /**
  6. * 苹果推荐 约束 增加和修改 放在此方法种
  7. */
  8. - (void)updateConstraints {
  9. [self.growingButton updateConstraints:^(MASConstraintMaker *make) {
  10. make.center.equalTo(self);
  11. make.width.equalTo(@(self.buttonSize.width)).priorityLow();
  12. make.height.equalTo(@(self.buttonSize.height)).priorityLow();
  13. make.width.lessThanOrEqualTo(self);
  14. make.height.lessThanOrEqualTo(self);
  15. }];
  16. //最后记得回调super方法
  17. [super updateConstraints];
  18. }
  • 如果想要约束变换之后实现动画效果,则需要执行如下操作
  1. // 通知需要更新约束,但是不立即执行
  2. [self setNeedsUpdateConstraints];
  3. // 立即更新约束,以执行动态变换
  4. // update constraints now so we can animate the change
  5. [self updateConstraintsIfNeeded];
  6. // 执行动画效果, 设置动画时间
  7. [UIView animateWithDuration:0.4 animations:^{
  8. [self layoutIfNeeded];
  9. }];

自动计算UITableViewCell高度

推荐使用一个库UITableView-FDTemplateLayoutCell

想法:动态高度的cell, 主要关注的点是什么?

  • viewController本身不需要知道cell的类型
  • cell的高度与viewController没有相关性,cell的高度由cell本身来决定
  • viewController真正做到的是一个

以下是摘抄过来的

主要是UILabel的高度会有变化,所以这里主要是说说label变化时如何处理,设置UILabel的时候注意要设置 preferredMaxLayoutWidth这个宽度,还有ContentHuggingPriority为 UILayoutPriorityRequried

  1. CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 10 * 2;
  2. textLabel = [UILabel new];
  3. textLabel.numberOfLines = 0;
  4. textLabel.preferredMaxLayoutWidth = maxWidth;
  5. [self.contentView addSubview:textLabel];
  6. [textLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  7. make.top.equalTo(statusView.mas_bottom).with.offset(10);
  8. make.left.equalTo(self.contentView).with.offset(10);
  9. make.right.equalTo(self.contentView).with.offset(-10);
  10. make.bottom.equalTo(self.contentView).with.offset(-10);
  11. }];
  12. [_contentLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

如果版本支持最低版本为iOS 8以上的话可以直接利用UITableViewAutomaticDimension在tableview的heightForRowAtIndexPath直接返回即可。

  1. tableView.rowHeight = UITableViewAutomaticDimension;
  2. tableView.estimatedRowHeight = 80; //减少第一次计算量,iOS7后支持
  3. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  4. // 只用返回这个!
  5. return UITableViewAutomaticDimension;
  6. }

但如果需要兼容iOS 8之前版本的话,就要回到老路子上了,主要是用systemLayoutSizeFittingSize来取高。步骤是先在数据model中添加一个 height的属性用来缓存高,然后在table view的heightForRowAtIndexPath代理里static一个只初始化一次的Cell实例,然后根据model内容填充数据,最后根 据cell的contentView的systemLayoutSizeFittingSize的方法获取到cell的高。具体代码如下

  1. //在model中添加属性缓存高度
  2. @interface DataModel : NSObject
  3. @property (copy, nonatomic) NSString *text;
  4. @property (assign, nonatomic) CGFloat cellHeight; //缓存高度
  5. @end
  6. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  7. static CustomCell *cell;
  8. //只初始化一次cell
  9. static dispatch_once_t onceToken;
  10. dispatch_once(&onceToken, ^{
  11. cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CustomCell class])];
  12. });
  13. DataModel *model = self.dataArray[(NSUInteger) indexPath.row];
  14. [cell makeupData:model];
  15. if (model.cellHeight <= 0) {
  16. //使用systemLayoutSizeFittingSize获取高度
  17. model.cellHeight = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 1;
  18. }
  19. return model.cellHeight;
  20. }

iOS Masonry的使用需要注意的地方的更多相关文章

  1. iOS masonry九宫格 单行 多行布局

    Masonry是个好东西,在当前尺寸各异的iOS开发适配中发挥着至关重要的作用,由于项目中Masonry布局用的比较多,对于UI布局也有了一些自己的理解,经常会有人问道Masonry布局九宫格要怎么布 ...

  2. iOS:Masonry介绍与使用

    Masonry介绍与使用实践:快速上手Autolayout   frame----->autoresing------->autoLayout-------->sizeClasses ...

  3. iOS masonry布局在iOS11/12上正常 iOS9/10却异常

    使用masonry布局,可以布局一套,适配所有机型,但是有时候会出现一些比较特殊的情况,每次iOS11上面开发,开发完成之后,在iOS9,iOS10上查看的时候发现布局与iOS11不完全一致,有的高度 ...

  4. iOS masonry 不规则tagView布局 并自适应高度

    在搜索页面经常会有不规则的tag出现,这种tagView要有点击事件,单个tagView可以设置文字颜色,宽度不固定根据内容自适应,高度固定,数量不固定.总高度就不固定.最近对于masonry的使用又 ...

  5. iOS Masonry控件等比例布局

    一.先解释相关API 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /**  *  distribute with fixed spacing  *  *  ...

  6. IOS Masonry自动布局

    之前项目用Frame布局,这个项目登录用了VFL,后来觉得用Masonry,前天布局TableViewCell时用了下 ,觉得还不错. #import "Masonry.h" #i ...

  7. iOS Masonry 查看更多 收起

    Masonry 查看更多 收起效果实现,带动画 demo下载地址: https://github.com/qqcc1388/MasonryDemo

  8. ios - masonry第三方库使用自动布局(参考:http://www.cocoachina.com/ios/20141219/10702.html)

    #import "ViewController.h" #import "Masonry.h" #define kWeakSelf(weakSelf) __wea ...

  9. iOS Masonry 抗压缩 抗拉伸

    约束优先级: 在Autolayout中每个约束都有一个优先级, 优先级的范围是1 ~ 1000.创建一个约束,默认的优先级是最高的1000 Content Hugging Priority: 该优先级 ...

随机推荐

  1. centos7下vi的用法

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  2. 11.python3标准库--使用进程、线程和协程提供并发性

    ''' python提供了一些复杂的工具用于管理使用进程和线程的并发操作. 通过应用这些计数,使用这些模块并发地运行作业的各个部分,即便是一些相当简单的程序也可以更快的运行 subprocess提供了 ...

  3. 学习笔记(二) 瓜娃(guava)的API快速熟悉使用

    1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection API Guava Basic Utilities IO API C ...

  4. Java学习(final、static关键词)

    final关键词 概念:final的意思为最终,不可变.final是个修饰符,它可以用来修饰类,类的成员,以及局部变量.不能修饰构造方法. 特点: 1.final修饰的类不可以被继承,但可以继承别的类 ...

  5. python3环境下面bytes类型转换成字典类型实例

    场景:通过http://tool.chinaz.com/tools/httptest.aspx在线HTTP接口测试工具获取接口的返回信息 { "status": 0, " ...

  6. PHP 中文乱码解决方式

    1.PHP代码在PHP Storm中乱码,设置PHP Storm的默认文件编码格式为UTF-8: 文件->设置->编辑器->文件编码->将所有默认编码调整为UTF-8: 2.对 ...

  7. 监控属性数组(Observables Arrays )

    如果你想发现并响应一个对象的改变,就应该用监控属性(observables).如果你想发现并响应一个集合的变化,就该用监控属性数组 (observableArray).监控属性数组在显示或编辑多个值以 ...

  8. 修改input中的placeholder属性的颜色

    input::-webkit-input-placeholder{ color:#e8e8e8; } input::-moz-placeholder{ /* Mozilla Firefox 19+ * ...

  9. 关于latex的画图

    可以使用latex画一些简单的图 可以参考这个链接:http://www.latexstudio.net/archives/9400(PGFPlots绘图简易教程[转载])

  10. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...