layoutSubviews 這個方法剂府,默認沒有做任何事情,需要子類進行重寫剃盾。
(This method) Lays out subviews.
Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews DO NOT offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.
以上節(jié)選自 UIView Class Reference
Whenever the size of a view changes, UIKit applies the autoresizing behaviors of that view’s subviews and THEN calls the layoutSubviews method of the view to let it make manual changes. You can implement the layoutSubviews method in custom views when the autoresizing behaviors by themselves DO NOT yield the results you want. Your implementation of this method can do any of the following:
Adjust the size and position of any immediate subviews.
Add or remove subviews or Core Animation layers.
Force a subview to be redrawn by calling its setNeedsDisplay or setNeedsDisplayInRect: method.
One place where applications often lay out subviews manually is when implementing a large scrollable area. Because it is impractical to have a single large view for its scrollable content, applications often implement a root view that contains a number of smaller tile views. Each tile represents a portion of the scrollable content. When a scroll event happens, the root view calls its setNeedsLayout method to initiate a layout change. Its layoutSubviews method then repositions the tile views based on the amount of scrolling that occurred. As tiles scroll out of the view’s visible area, the layoutSubviews method moves the tiles to the incoming edge, replacing their contents in the process.
以上節(jié)選自 View Programming Guide for iOS
根據(jù)官方文檔的描述腺占,可以知道 layoutSubviews 主要是為了讓我們?nèi)崿F(xiàn)UIView的策略來布局以及排列等淤袜,這樣就可以保證我們在需要新的布局方案的時候,父類UIView 會按照我們制定的方案去布局衰伯。我們在某個類的內(nèi)部調(diào)整子視圖位置時铡羡,需要調(diào)用。反過來的意思就是說:如果你想要在外部設置 sub views 的位置意鲸,就不要重寫烦周。而且,layoutSubviews 方法只能被系統(tǒng)觸發(fā)調(diào)用怎顾,不可以手動去調(diào)用读慎。 要引起該方法的調(diào)用,可以調(diào)用 UIView 的 setNeedsLayout 方法來標記一個 UIView杆勇。這樣一來贪壳,在 UI 線程的下次繪制循環(huán)中,系統(tǒng)便會調(diào)用該 UIView 的 layoutSubviews 方法蚜退。
在蘋果的官方文檔中強調(diào):
You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want.
layoutSubviews, 當我們在某個類的內(nèi)部調(diào)整子視圖位置時闰靴,需要調(diào)用;如果你想要在外部設置subviews的位置钻注,就不要重寫蚂且。
layoutSubviews 默認沒有做任何事情,既然我不能手動直接調(diào)用該方法幅恋,那在什么時候杏死、何種條件下這個方法會被調(diào)用呢?
Stackoverflow 上已經(jīng)有相關的討論了(作者在他的博客上有更詳細的描述)捆交,并且有一位朋友給出了很不錯的解答:
- init does not cause layoutSubviews to be called (duh)
- addSubview causes layoutSubviews to be called on the view being added, the view it’s being added to (target view), and all the subviews of the target
- view setFrame intelligently calls layoutSubviews on the view having its frame set only if the size parameter of the frame is different
- scrolling a UIScrollView causes layoutSubviews to be called on the scrollView, and its superview
- rotating a device only calls layoutSubview on the parent view (the responding viewControllers primary view)
- Resizing a view will call layoutSubviews on its superview
翻譯:
- init初始化不會觸發(fā)layoutSubviews 但是是用initWithFrame 進行初始化時淑翼,當rect的值不為CGRectZero時,也會觸發(fā)
- addSubview會觸發(fā)layoutSubviews
- 設置view的Frame會觸發(fā)layoutSubviews,當然前提是frame的值設置前后發(fā)生了變化
- 滾動一個UIScrollView會觸發(fā)layoutSubviews
- 旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件
- 改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件
iOS 中 layout 的相關方法:
- layoutSubviews
- layoutIfNeeded
- setNeedsLayout
- setNeedsDisplay
- drawRect
- sizeThatFits
- sizeToFit
當然這并不齊全品追。
1. setNeedsLayout方法:
標記為需要重新布局玄括,異步調(diào)用layoutIfNeeded刷新布局,不立即刷新肉瓦,但layoutSubviews一定會被調(diào)用
2. layoutIfNeeded方法:
如果有需要刷新的標記遭京,立即調(diào)用layoutSubviews進行布局;如果沒有標記泞莉,不會調(diào)用layoutSubviews哪雕;如果要立即刷新,要先調(diào)用[view setNeedsLayout]鲫趁,把標記設為需要布局斯嚎,然后馬上調(diào)用[view layoutIfNeeded],實現(xiàn)布局饮寞。在視圖第一次顯示之前孝扛,標記總是“需要刷新”的列吼,可以直接調(diào)用[view layoutIfNeeded]
3. 重繪
drawRect方法:重寫此方法幽崩,執(zhí)行重繪任務
setNeedsDisplay方法:標記為需要重繪苦始,異步調(diào)用drawRect
setNeedsDisplayInRect方法:標記為需要局部重繪
4. sizeToFit
sizeToFit會自動調(diào)用sizeThatFits方法;
sizeToFit不應該在子類中被重寫慌申,應該重寫sizeThatFits
sizeThatFits傳入的參數(shù)是receiver當前的size陌选,返回一個適合的size
sizeToFit可以被手動直接調(diào)用
sizeToFit和sizeThatFits方法都沒有遞歸,對subviews也不負責蹄溉,只負責自己
Tips:
layoutSubviews對subviews重新布局
layoutSubviews方法調(diào)用先于drawRect
setNeedsLayout在receiver標上一個需要被重新布局的標記咨油,在系統(tǒng)runloop的下一個周期自動調(diào)用layoutSubviews
layoutIfNeeded方法如其名,UIKit會判斷該receiver是否需要layout.根據(jù)Apple官方文檔,layoutIfNeeded方法應該是這樣的
layoutIfNeeded遍歷的不是superview鏈柒爵,應該是subviews鏈
drawRect是對receiver的重繪役电,能獲得context
setNeedDisplay在receiver標上一個需要被重新繪圖的標記,在下一個draw周期自動重繪棉胀,iphone device的刷新頻率是60hz法瑟,也就是1/60秒后重繪