重繪佈局等方法使用說明

weixin_33890499發表於2016-07-05

1.layoutIfNeeded、setNeedsLayout:
-setNeedsLayout方法: 標記為需要重新佈局,非同步呼叫layoutIfNeeded重新整理佈局,不立即重新整理,但layoutSubviews一定會被呼叫

-layoutIfNeeded方法:如果,有需要重新整理的標記,立即呼叫layoutSubviews進行佈局(如果沒有標記,不會呼叫layoutSubviews
如果要立即重新整理,要先呼叫[view setNeedsLayout],把標記設為需要佈局,然後馬上呼叫[view layoutIfNeeded],實現佈局

在檢視第一次顯示之前,標記總是“需要重新整理”的,可以直接呼叫[view layoutIfNeeded]

2.layoutSubviews
-layoutSubviews方法:這個方法,預設沒有做任何事情,需要子類進行重寫

layoutSubviews在以下情況下會被呼叫:

  • init初始化不會觸發layoutSubviews
    但是是用initWithFrame 進行初始化時,當rect的值不為CGRectZero時,也會觸發
  • addSubview會觸發layoutSubviews
  • 設定view的Frame會觸發layoutSubviews,當然前提是frame的值設定前後發生了變化
  • 滾動一個UIScrollView會觸發layoutSubviews
  • 旋轉Screen會觸發父UIView上的layoutSubviews事件
  • 改變一個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的位置,就不要重寫。

3.重繪
-drawRect:(CGRect)rect方法:重寫此方法,執行重繪任務
-setNeedsDisplay方法:標記為需要重繪,非同步呼叫drawRect
-setNeedsDisplayInRect:(CGRect)invalidRect方法:標記為需要區域性重繪

  • 如果在UIView初始化時沒有設定rect大小,將直接導致drawRect不被自動呼叫。
  • 該方法在呼叫sizeThatFits後被呼叫,所以可以先呼叫sizeToFit計算出size。然後系統自動呼叫drawRect:方法。
  • 通過設定contentMode屬性值為UIViewContentModeRedraw。那麼將在每次設定或更改frame的時候自動呼叫drawRect:
  • 直接呼叫setNeedsDisplay,或者setNeedsDisplayInRect:觸發drawRect:,但是有個前提條件是rect不能為0.

以上1,2推薦;而3,4不提倡

  1. 若使用UIView繪圖,只能在 drawRect:方法中獲取相應的contextRef並繪圖。如果在其他方法中獲取將獲取到一個invalidate的ref並且不能用於畫圖。drawRect:方法不能手動顯示呼叫,必須通過呼叫setNeedsDisplay 或者 setNeedsDisplayInRect,讓系統自動調該方法。
  2. 若使用calayer繪圖,只能在drawInContext:中(類似魚drawRect)繪製,或者在delegate中的相應方法繪製。同樣也是呼叫setNeedDisplay等間接呼叫以上方法。
  3. 若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時重新整理螢幕

小結:

  • layoutSubviews對subviews重新佈局
  • layoutSubviews方法呼叫先於drawRect
  • setNeedsLayout在receiver標上一個需要被重新佈局的標記,在系統runloop的下一個週期自動呼叫layoutSubviews

4.sizeToFit

  • sizeToFit會自動呼叫sizeThatFits方法;
  • sizeToFit不應該在子類中被重寫,應該重寫sizeThatFits
  • sizeThatFits傳入的引數是receiver當前的size,返回一個適合的size
  • sizeToFit可以被手動直接呼叫
  • sizeToFitsizeThatFits方法都沒有遞迴,對subviews也不負責,只負責自己

相關文章