Autolayout

Content Hugging 和 Content Compression Resistance

  • Content Compression Resistance = 不许挤我!这个属性的优先级(Priority)越高,越不“容易”被压缩。
  • Content Hugging = 抱紧!也就是View的大小不会随着父级View的扩大而扩大。

自动高度的表格

  • 需要自我约束的cell
    • Cell里面的每一个View的大小、位置,都可以从约束中得到体现,
    • 而Cell的整体大小,也是从子View的约束综合计算得出的。
    • 基本上,保证
      1. 内容不会变的元素,给死大小
      2. 最左,最右,最上,最下的元素一定要设置到上下左右的边距
  • UILabelpreferredMaxLayoutWidth
    • 如果我们要使用Autolayout自动计算多行UILabel的高度,这个属性就必须在运行时指定,要不然系统计算不出UILabel的宽度
    • 一般给个足够长的宽度就好了,比如容器宽度,屏幕宽度等
    • 所以这里也是我我没看懂的地方,实测也不是非有不可,可以留作debug用
  • systemLayoutSizeFittingSize:获取Cell的高度
    • UILayoutFittingCompressedSize: 返回合适的最小大小。
    • UILayoutFittingExpandedSize: 返回合适的最大大小。
    • [_templateCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]
  • iOS 8以后:

tableView.rowHeight = UITableViewAutomaticDimension;
tableView.estimatedRowHeight = 80;

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // 只用返回这个!
    return UITableViewAutomaticDimension;
}

一个cell里并排多个元素(比如label),自动高度

保证每个元素的底部都小于等于cell的底边,这样就不需要去手动计算哪个最高了

topLayoutGuide和bottomLayoutGuide

  • 代表的是头部导航条,状态条,底部的tabBar, 工具条等区域
  • 这两个属性是UIViewController的属性,不是UITableView的。
  • 用法1,它们是UIView的子类,所以它们也有UIViewframe等属性。
    • 当作view来用make.top.equalTo(topLayoutGuide.mas_bottom);
    • 但是做autolayout的时候,它们是UILayoutSupport的子类,所以不能直接用mas_来操作。 << 这是智能提示出来的,也就是说尽量别这么用
    • 它们的高度是固定的,不能设置mas_来设置高度
  • 用法2,一般使用length属性获取其实时高度就好了
    • make.top.equalTo(self.view.mas_top).with.offset(self.topLayoutGuide.length);
  • 用法3,使用新版的mas_topLayoutGuidemas_bottomLayoutGuide
    • 在Masonry的新版中,为UIViewController增加了一个新的Category: MASAdditions,增加了mas_topLayoutGuidemas_bottomLayoutGuide两个方法
    • make.top.equalTo(self.mas_topLayoutGuide);

baseline

  • 在Autolayout里面对应着NSLayoutFormatAlignAllBaseline
  • UILabel里baseline是文字的底部
  • UIButton里baseline是UILabel的文字底部
  • 自定义的View默认是整个view的底部
  • 重写viewForBaselineLayout
    • 返回一个UIView,这个UIView的baseline就是整个view的底部

约束变量

  • 建立约束时保存: _parallaxHeaderHeightConstraint = make.height.equalTo(@(ParallaxHeaderHeight));
  • 事后修改:_parallaxHeaderHeightConstraint.equalTo(@(ParallaxHeaderHeight - scrollView.contentOffset.y));

Priority

  • 默认优先级是1000
  • .priorityHigh()反而只有750

InstrinsicContentSize

  • 当一个控件的intrinsicContentSize被设置后,它的sizeToFit方法就失效了
    • 注意:intrinsicContentSize的值是CGSizeZero时,sizeToFit方法才会生效
  • 自动布局时有这个“原生大小”的概念,
    • 可以在计算多个视图的比例时使用,即使每个视图的大小是可变的,比例就按intrinsicContentSize里的值来计算
    • 也可以在自定义摆放子view的场景下,指定容器视图大小的计算方式
    • 当自定义视图大小是可变的时,想要容器实时感知它的大小,需要在实时计算后invalidateIntrinsicContentSize
    • 实时计算并invalidate的时机最好写在如下方法里:
      1. intrinsicContentSize的getter方法
      2. layoutSubviews方法

多重约束

  • 对同一个约束设置多次,只要不冲突,是会自动计算到正确的位置的
  • 比如a.left >= b.right, >= c.right, >= d.right,这样b,c,d哪个最宽,a就在哪个右边(自然也在其它两个右边了)