ios - layoutifneeded




layoutSubviews何時被調用? (7)

我有一個自定義視圖,它不會在動畫過程中獲取layoutSubview消息。

我有一個填充屏幕的視圖。 如果我更改導航欄的高度,它會在界面生成器中正確調整大小的屏幕底部有一個自定義子視圖。 layoutSubviews在創建視圖時調用,但不會再次。 我的子視圖已正確佈置。 如果我關閉了通話狀態欄,那麼即使主視圖執行其調整大小動畫,子視圖的layoutSubviews也不會被調用。

layoutSubviews在什麼情況下實際調用?

我的autoresizesSubviews設置為NO用於我的自定義視圖。 在界面生成器中,我有頂部和底部支柱和垂直箭頭組。


https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1

只要在視圖中發生以下任何事件,就會發生佈局更改:

一個。 視圖邊界矩形的大小發生變化。
灣 出現界面方向更改,通常會觸髮根視圖邊界矩形中的更改。
C。 與視圖圖層關聯的Core Animation子圖層組發生更改並需要佈局。
d。 您的應用程序通過調用視圖的setNeedsLayoutlayoutIfNeeded方法來強制執行佈局。
即 您的應用程序通過調用視圖底層對象的setNeedsLayout方法來強制佈局。


layoutSubviews永遠不會被調用的時候,一個比較隱晦但可能很重要的情況是:

import UIKit

class View: UIView {

    override class var layerClass: AnyClass { return Layer.self }

    class Layer: CALayer {
        override func layoutSublayers() {
            // if we don't call super.layoutSublayers()...
            print(type(of: self), #function)
        }
    }

    override func layoutSubviews() {
        // ... this method never gets called by the OS!
        print(type(of: self), #function)
    }
}

let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

你看過layoutIfNeeded嗎?

文檔片段如下。 如果在動畫期間顯式調用此方法,動畫是否工作?

layoutIfNeeded根據需要放置子視圖。

- (void)layoutIfNeeded

討論使用此方法可在繪製之前強制子視圖的佈局。

可用性在iPhone OS 2.0及更高版本中可用。


基於@BadPirate先前的回答,我進一步嘗試了一些,並提出了一些澄清/更正。 我發現layoutSubviews:只會在以下情況下在視圖上調用:

  • 它自己的界限 (不是框架)改變了。
  • 其中一個直接子視圖的界限發生了變化。
  • 子視圖被添加到視圖或從視圖中刪除。

一些相關細節:

  • 只有在新值不同的情況下才會更改邊界, 包括不同的原點 。 特別注意這就是為什麼layoutSubviews:在UIScrollView滾動時調用,因為它通過更改邊界的原點來執行滾動。
  • 改變框架只會改變邊界,如果大小已經改變,這是唯一傳播到邊界屬性。
  • 尚未處於視圖層次結構中的視圖邊界的更改將導致對layoutSubviews:的調用layoutSubviews: 視圖最終添加到視圖層次結構中時
  • 只是為了完整:這些觸發器不直接調用layoutSubviews,而是調用setNeedsLayout ,它設置/引發一個標誌。 運行循環的每次迭代中,對於視圖層次結構中的所有視圖,都將檢查此標誌。 對於發現標誌的每個視圖,調用layoutSubviews:並重置該標誌。 首先檢查/調用層次較高的視圖。

我將解決方案跟踪到Interface Builder的堅持,即在模擬屏幕元素打開的視圖(狀態欄等)上不能更改彈簧。 由於主視圖中的彈簧已關閉,該視圖無法改變大小,因此在出現呼叫欄時全部向下滾動。

關閉模擬功能,然後調整視圖大小並正確設置彈簧,導致動畫發生,並調用我的方法。

調試時遇到的另一個問題是,當通過菜單切換通話狀態時,模擬器會退出應用程序。 退出應用程序=無調試器。


我有一個類似的問題,但不滿意答案(或任何我可以在網上找到的),所以我在實踐中嘗試了這一點,這就是我得到的:

  • init不會導致layoutSubviews被調用(duh)
  • addSubview:使layoutSubviews在被添加的視圖,被添加到的視圖(目標視圖)和目標的所有子視圖上被調用
  • 只有當幀的大小參數不同時, setFrame在視圖上setFrame調用layoutSubviews
  • 滾動UIScrollView會導致layoutSubviews在scrollView和它的超級視圖上被調用
  • 旋轉設備只調用父視圖上的layoutSubview (響應的viewControllers主視圖)
  • 調整視圖大小將調用其超視圖上的layoutSubviews

我的結果 - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/


這個難題的另一個部分是窗戶必須是關鍵的:

[window makeKeyAndVisible];

其他子視圖不會自動調整大小。





layoutsubviews