UIScrollview的 约束 contentsize contentoffset contentinset layoutsubviews needlayout等影响布局的属性

  很久没有写视图布局,最近发现写布局很不顺手,总结一下在处理UIScrollview的时候种种注意事项:

1.

self.automaticallyAdjustsScrollViewInsets = NO;

iOS7之后,当你在Nav上添加TableView的时候,你会发现tableView的位置并不是从你的起点开始的 ,这是因为在iOS7之后,如果nav上添加的第一个视图是UIScrollView的时候,系统会默认添加上64的间隔,解决方法是  你把第一个视图添加一个0.1的View使SCrollView成为第二个视图,或者取消系统默认效果.。

2.

关于layoutsubviews 和 setNeedsLayout, layoutIfNeeded

最近我在一个controller上面添加了一个controller,子controller上面是一个tableview,我需要获取tableview的偏移量来赋值给父类controller上滚动视图,使父类视图能够正常滑动。由于重新赋值了子类的frame,所以我预先标记了tableview:

   [self.historyInfoVc.tableview layoutIfNeeded];

  发现位置并非想象的那样,tableview进行了重新布局,但是子类控制器的view并未进行重新布局,这导致我的视图上出现了两个tableview错乱排列的情况,具体为什么出现这种情况我也不是很清楚。后来我把重新布局的属性改为了子类控制器的view,子类控制器的view在重新布局的时候一定会连并subviews一起布局,发现果然可行。关于这三个属性在此进行说明如下:

1、init初始化不会触发layoutSubviews 但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发

2、addSubview会触发layoutSubviews

3、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化

4、滚动一个UIScrollView会触发layoutSubviews

5、旋转Screen会触发父UIView上的layoutSubviews事件

6、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件 

刷新子对象布局

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局

在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]

重绘

-drawRect:(CGRect)rect方法:重写此方法,执行重绘任务
-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘

sizeToFit会自动调用sizeThatFits方法;

sizeToFit不应该在子类中被重写,应该重写sizeThatFits

sizeThatFits传入的参数是receiver当前的size,返回一个适合的size

sizeToFit可以被手动直接调用

sizeToFit和sizeThatFits方法都没有递归,对subviews也不负责,只负责自己

———————————-

layoutSubviews对subviews重新布局

layoutSubviews方法调用先于drawRect

setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews

layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.根据Apple官方文档,layoutIfNeeded方法应该是这样的

layoutIfNeeded遍历的不是superview链,应该是subviews链

drawRect是对receiver的重绘,能获得context

setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz
,也就是1/60秒后重绘 

3.contentsize

也许你并未发现这东西能出现什么问题,但是作为scrollview来讲,在存在约束的情况下,或者你已经摸不着头脑了。

在官方文档上有这么一句话:

scrollView使用自动约束是要特别小心,使用自动约束之后,scrollView.contentSize会根据它的subviews来进行计算,
所以一定要保证添加到scrollView里的subview的宽高是可以确定的值,并且要和scrollView的edge进行正确的约束

也就是说如果你在给scrollview添加子控件的时候,如果是使用约束来实现的话,那么你就需要⚠️,通常,如果不需要适配横屏的话我就直接添加frame;

4.contentinset

其实很好理解,就是scroview的显示内容距离该scrollview的间距。但是我在设置的时候发现下和右都无法正常使用,查了很多资料也找不到其中缘由?知道的伙伴请指教,不胜感激!

  

原文地址:https://www.cnblogs.com/lidarui/p/6518628.html