AutoLayout

AutoLayout

关于 autolayout

  • 一般来说, 控件设置 autolayout 要是约束不全的话会报提醒, 因为位置/大小两个因素, 缺少了都不能确定位置
  • 但是有些控件比较特别, 少了某个约束不会报错, 因为系统会自动计算其某个约束属性, 像 Label, 会计算其高度, 跟随文字的多少而变化, 但是这样必须不限制行数

在返回数据不确定是什么数值, 想精确保留的话不要转成基本类型, 应该用 NSNumber 接收, 这样是什么样子的数传进来还是什么数
在返回的 json 属性里, 要算有属性中还有属性的, 一般这个属性可以转成一个对象, MJ 框架会自动判断类型, 我们只要写个类接收这个参数就行了

UIlabel 自动布局自适应高度

  • 当设置好约束后, 设置其 preferredMaxLayoutWidth, uiview 有个方法: systemLayoutSizeFittingSize:UILayoutFittingCompressedSiz可以拿到根据自动布局约束来获得紧凑的 Size, 这时可以拿到高,
  • 但是 UILabel 没有设置选中文字, 也没有获取相对 rect 的方法, 默认也不能点击富文本的链接, 只能通过 UITextView 来显示富文本, 通过算出 link 的 rect, 判断是否点中, 发出通知来传递链接信息

UITextView 的高度自适应

  • 根据文字内容的多少, 决定高度, 如果不设置宽度, 就会根据富文本的换行来决定宽度,
  • CGSize size = [self sizeThatFits:CGSizeMake(width, MAXFLOAT)]; 根据宽度来适应的 Size, 这里高度无限, 即未达到这个高度时会根据内容的实际尺寸, 超过了就安装设定的尺寸, 这样就能按照内容来设定高度了, 在获取这个之前, 要先有内容填充进去, 所以在内容填充时还要在设置这个方法才行, 为了保险, 在 layoutSubViews 中在设置一下也好

UItableViewCell 的高度自适应

  • 将 cell 中的子控件都设置上约束, 让 cell 上四边都和子控件有约束, 在 iOS8之前, 可以像上面那样获取 label 的高度, 再设置 cell 的高, 也可以用一个模板 cell, 里面是约束好的控件, 将内容填入, 再 sizetoFit…. 就能拿到自适应的高
  • iOS8开始, 只要设置好了约束, 在 tabelView 设置 estimateHei, 预估高度, 还有 rowheight= UITableViewAutomaticDimension;就可以了,,,,,,heiorrowAtIndexPath 这个代理方法都不用实现
  • 可以用 beginUpdate / endUpdate 来更新 tableView

Bug

  • 将做好的显示属性文本的控件加到一个 view(containView) 上时, 虽然 view 可以根据里面 textView 的变化改变 size, 但是在更外满一层使用这个控件的 view, 不能根据containView 的 size 改变而改变, 只能拿到这个 containview 的高, 加上其自己本来能自动布局的高,

注意: 在自定义控件的时候, 最好 initWithFrame 和 initWithCoder 一起实现, 将初始化代码放在 setup 类似的方法里在上面两个方法中调用, 免得在 xib 使用时没有调用其初始化方法,

  • systemLayoutSizeFittingSize:UILayoutFittingCompressedSize的坑:
    在使用这个方法时, 只能自适应其中固定了尺寸宽高的控件, 像自己做的这个显示富文本的控件, 放在一耳光 view 里了, 默认 view 没有自动适应内容高度, 所以外面在fit 的时候, 就不会将这个 view 考虑在内, 或者考虑为0, 所以需要自己拿到改变的高自己计算高度

注意: sizeThatFits的坑: 这个如果宽度不够, 一样只会取最少的返回, 所以要固定宽的话, 也要另外设置

  • SQL 数据库要搜索的字段是TEXT的话, 执行语句里要加上’’

  • scrollView 在使用自动布局时, 设置了上下左右后还是会提示有错, 有约束没有设置, 而且运行后有时滚动不了

先猜想: 其布局和普通控件不一样, 果然, 它除了 pin 在四周的设置外, 还会根据子控件来设置其 contentSize, 没有足够的约束来计算的话就会报错, 可以在 scrollView 里设置一个 contentView 来填充其内部, 所有要在滚动视图的子控件都加在 contentView 中, 而且子控件要连贯其上下或者左右来设置约束, 这样这个 contetntView 就会根据内部的子控件来计算 size, scrollView 是根据这个 contentView 来算 contentSize, 如果不想哪个方向滚动, 可以设置 contentView 的高/宽 = scrollView.高/宽, 相当于 contentSize 的高.宽被设定死了, 在高/宽方向不滚动, Google 后发现其底部和右边的约束是对其 contentSize 的设置, 即约束里的 width 和 height 是对其滚动范围的设置
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html

  • 代码设置 contentOffset = xx, 无效, setContentOffset:animated:方法无效

cao !!其实是有效果的1!!! 在更换了 xib 文件中的控件时忘了重新联建 scrollVIew! 到时其 = nil;
在网上找到些这些问题的方法, 记录下, 以后要是真碰到了无效的话试试.

1
2
3
4
5
6
1. 强制回主线程操作:
dispatch_async(dispatch_get_main_queue(), ^{
这里设置 offset
});
2. pagingEnable = no;, 设置完 offset 再设置回来
3. delegate = no; 设置完 offset 再设置回来
  • 这是在搜上面的问题时顺便搜到的, 以后可能有用, 问题是当 pop 会 scrollview 时, 里面的控件和 tabbar 会有奇怪的布局现象, 解决方法

In iOS 7/8/9 simple self.automaticallyAdjustsScrollViewInsets = NO; solved the problem in my case. 原文连接: http://stackoverflow.com/questions/17404682/uiscrollviews-origin-changes-after-popping-back-to-the-uiviewcontroller
-warning: 关于 textView 内容更新及其尺寸的更新
在内容更新后, 会自动更新内容, 但是设置的大小, 要先[self.attView sizeToFit], 或 sizeThatFit:方> 法重新计算, 其容器才能根据这个 textView自动计算出来的尺寸设置其他东西, 而且要在外层

关于 View 布局的注意, 当 view

// [la setNeedsLayout]; // 可以, 这个方法会调用其中的 updateConstrains 和 layoutSubviews 方法
// [la setNeedsDisplay]; // 不行, 只会调用updateConstraints
// [la setNeedsUpdateConstraints]; // 不行, 只会调用updateConstraints
[self invalidateIntrinsicContentSize] // 当改变了内部内容的尺寸时, 要调用这个

所以, 当想要都调用 View 中两个方法的话, 只能使用setNeedsLayout

textView 布局注意

  • 在设置好宽度后, 直接 sizeToFit 就可以或者 sizeThatFit:, 但是在 view 中直接用textVIew的话好像不行, 要自定义一个 tetxView, 在 layoutSubView 中实现重新设置 size 才可以…
  • 目前在 textView 的属性文本中添加的图片如果修改了尺寸的话, 好像它还是按照原来的尺寸来适应这个高度, 还要设置 attach.bounds 才能按照这个 bounds 来布局