layoutSubviews、drawRect与sizeToFit

1.layoutSubviews
官方说明:
这个方法,默认没有做任何事情,子类可以根据需要覆盖此方法,以执行其子视图的更精确布局。
您不应该直接调用此方法。 如果要强制进行布局更新,请在下次绘图更新之前调用setNeedsLayout方法。
如果要立即更新视图的布局,请调用layoutIfNeeded方法。
调用时机:
1.init初始化不会触发layoutSubviews;但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时, addSubview也会触发
2.addSubview会触发layoutSubviews
3.设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化(因此在layoutSubviews中设置frame不会造成循环);
4.滚动一个UIScrollView会触发layoutSubviews
5.旋转Screen会触发父UIView上的layoutSubviews事件
6.单纯改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件
7.setNeedsLayout方法(异步)、-layoutIfNeeded方法(马上)会调用layoutSubviews进行布局
总结:layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。
-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局。
layoutSubviews方法调用先于drawRect


2.drawRect:(CGRect)rect执行重绘任务
可以在UIView(UIViewRendering)的方法- (void)drawRect:(CGRect)rect;中去绘制一些我们所需要的图形,如虚线、圆形、方形以及曲线等等图形 ,重写此方法,执行重绘任务。
调用时机:
1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用;在子类初始化时调用- (instancetype)initWithFrame:(CGRect)frame方法,且frame不为CGRectZero时会调用
2、该方法在调用sizeThatFits后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0.
5、drawRect是在Controller->loadView, Controller->viewDidLoad之后会自动调用,调用时机是在viewWillAppear和viewDidAppear之间
使用说明:
只能在继承了UIView的子类中通过重写drawRect方法来绘制图形; 如果需要绘制图形的子类直接继承自UIView,则子类的drawRect方法中不需要调用父类方法[super drawRect:rect];如果子类继承自其他继承UIView的View类,则drawRect方法中需要调用父类方法[super drawRect:rect];
补充:
-setNeedsDisplay方法:标记为需要重绘,异步掉用drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘
比较:
layoutSubviews对subviews重新布局;drawRect是对receiver的重绘,能获得context;
layoutSubviews方法调用先于drawRect;
setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews;layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout.
layoutIfNeeded遍历的不是superview链,应该是subviews链
setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘。


3.sizeToFit: resize当前view,使得它找到最适合自己的大小.通常是通过view内容来确定它自己的大小.不要重写这个方法.
sizeToFit会计算出最优的 size 而且会改变自己的size
sizeThatFits: 会计算出最优的 size 但是不会改变 自己的size
使用这两个方法必须先给label赋值。
常用场景
UILabel中,先设置label view的width,然后使用sizeToFit,会根据内部文字多少,自适应返回当前label的size,其中height就是系统自动计算的.(ps:这里也可以用NSString的boundingRect方法计算文字宽高,然后设置给label)
UIImageView, 如果该imageView中有图片,调用sizeToFit,返回的size就是内部图片的size
UISwitch, 这个控件的默认size是固定的,调用以后返回默认的size.(ps:如果需要改变大小,使用transform属性)
navigationItem, 如果设置它使用customView时候,最好先调用sizeToFit
补充:UILabel中有一个关键属性adjustsFontSizeToFitWidth,可以通过label的width反向自适应设置字体的font.注意这个属性需要配合baselineAdjustment=UIBaselineAdjustmentAlignCenters一起使用.

你可能感兴趣的:(layoutSubviews、drawRect与sizeToFit)