[转]layout subview

原始出处不知道在哪,这里转下;谢谢!

 

layoutSubviews总结

ios layout机制相关方法

- (CGSize)sizeThatFits:(CGSize)size
- (void)sizeToFit
——————-

- (void)layoutSubviews
- (void)layoutIfNeeded
- (void)setNeedsLayout
——————–

- (void)setNeedsDisplay
- (void)drawRect
layoutSubviews在以下情况下会被调用:

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事件

在苹果的官方文档中强调:

      You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want.

layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。

反过来的意思就是说:如果你想要在外部设置subviews的位置,就不要重写。

刷新子对象布局

// Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early

- (void)setNeedsLayout;

- (void)layoutIfNeeded;


-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秒后重绘 

 

When the moment comes to lay out a view, the following events take place:

  1. The view and its subviews are sent updateConstraints, starting at the bottom of the hierarchy (the deepest subview) and working up to the top (the view itself, possibly the root view). This event may be omitted for a view if its constraints have not changed.

    You can override updateConstraints in a subclass. You might do this, for example, if your subclass is capable of altering its own constraints and you need a signal that now is the time to do so. You must call super or the app will crash (with a helpful error message). You should never call updateConstraints; to trigger an immediate call to updateConstraints, send a view the updateConstraintsIfNeeded message.

    If you’re not using autolayout, updateConstraints by default won’t be sent to your view as part of the layout process. If you want it to be sent, sendsetNeedsUpdateConstraints to the view. You’ll then get updateConstraints events from then on, whenever layout is to be performed.

  2. The view and its subviews are sent layoutSubviews, starting at the top of the hierarchy (the view itself, possibly the root view) and working down to the bottom (the deepest subview).

    You can override layoutSubviews in a subclass in order to take a hand in the layout process. If you’re not using autolayout, layoutSubviews does nothing by default;layoutSubviews is your opportunity to perform manual layout after autoresizing has taken place. If you are using autolayout, you must call super or the app will crash (with a helpful error message). You should never call layoutSubviews; to trigger an immediate call to layoutSubviews, send a view the layoutIfNeededmessage (which may cause layout of the entire view tree, not only below but also above this view), or send setNeedsLayout to trigger a call to layoutSubviews later on, after your code finishes running, when layout would normally take place.

When you’re using autolayout, what happens in layoutSubviews? The runtime examines all the constraints affecting this view’s subviews, works out values for their frames, and assigns those views those frames. In other words, layoutSubviews performs manual layout! The constraints are merely instructions attached to the views;layoutSubviews reads them and responds accordingly, setting frames in the good old-fashioned way.

Knowing this, you might override layoutSubviews when you’re using autolayout, in order to tweak the outcome. First you call super, causing all the subviews to adopt their new frames. Then you examine those frames. If you don’t like the outcome, you can change the situation, removing subviews, adding or removing constraints, and so on — and then you call super again, to get a new layout outcome.

Unless you explicitly demand immediate layout, layout isn’t performed until your code finishes running (and then only if needed). Moreover, ambiguous layout isn’t ambiguous until layout actually takes place. Thus, for example, it’s perfectly reasonable to cause an ambiguous layout temporarily, provided you resolve the ambiguity beforelayoutSubviews is called. (Your last best opportunity to do this is in updateConstraints!) That’s why it was legal for me, in the code at the end of the preceding section, to remove two constraints before adding some new ones; there was briefly an ambiguous layout situation, but no layout took place during that time.

 

posted @ 2014-08-14 17:58  wtndcs  阅读(367)  评论(0编辑  收藏  举报