Autolayout的Top Layout guide問題

iOS開發——Autolayout的Top Layout guide問題

寫這篇博客以前,真想大吼一聲:Top Layout Guide,你究竟是什麼鬼!html

問題描述

在學習UIPageViewController的過程當中,按照《【譯】如何使用Storyboard建立UIPageViewController》編寫引導頁Demo,可是作完的效果和Demo效果有一些出入,效果分別爲:正確效果錯誤效果ide

簡單說就是當滑動到下一頁的時候,下一頁會有一個縮小效果,可是這個效果並非手動添加的。佈局

分析問題

以前的那篇《iOS學習筆記——UIScrollView的坑和填坑》中提到了Autolayout的問題:自動添加Constraints致使出錯。此次要說的問題和上次都和一個東西有關——Top Layout Guide。學習

Top Layout Guide用於自動佈局的輔助,在Storyboard中能夠看到Top Layout Guide做爲ViewController的屬性存在,也就是topLayoutGuide,官方文檔對這個屬性的Discussion是:ui

topLayoutGuide屬性表示不但願被透明的狀態欄或導航欄遮擋的內容範圍的最高位置。這個屬性的值是它的length屬性的值(topLayoutGuide.length),這個值可能由當前的ViewController或這個ViewController所屬的NavigationController或TabBarController決定,有以下狀況:spa

  • 一個獨立的ViewController,不包含於任何其餘的ViewController。若是狀態欄可見,topLayoutGuide表示狀態欄的底部,不然表示這個ViewController的上邊緣。htm

  • 包含於其餘ViewController的ViewController不對這個屬性起決定做用,而是由容器ViewController決定這個屬性的含義:生命週期

    • 若是導航欄(Navigation Bar)可見,topLayoutGuide表示導航欄的底部。開發

    • 若是狀態欄可見,topLayoutGuide表示狀態欄的底部。文檔

    • 若是都不可見,表示ViewController的上邊緣。

這部分還比較好理解,總之是屏幕上方任何遮擋內容的欄的最底部。

經過對ViewController的生命週期消息進行跟蹤,在下一頁顯示出來前,首先調用下一頁ViewController的viewDidLoad方法,也就是加載過程,此時topLayoutGuide值爲0;而顯示的消息viewWillAppear:和佈局的消息viewWillLayoutSubview在放開手指以後纔會發送,而這個時候已經徹底顯示了,topLayoutGuide的值爲20,也就是在狀態欄下邊緣。

當鬆手的時候,topLayoutGuide的值發生的這一個變化,就致使咱們看到了一個忽然縮小的效果。

解決問題

到如今爲止,找到了兩個解決方法,不過並不完美。

方法一:在設置自動佈局約束時,不使用Top Layout Guide,而是使用父View的上邊緣。

說方法二以前,還要在說一下AutoLayout的設置,默認添加的約束是這樣的:

屏幕快照 2014-10-22 下午3.48.30

注意第二項Top Layout Guide.Bottom,也就是約束到topLayoutGuide的下邊緣,也就是說topLayoutGuide是有高度的!!

再次查文檔中對length的解釋:

The top layout guide indicates the distance, in points, between the top of a view controller’s view and the bottom of the bottommost bar that overlays the view.

能夠看到是指當前ViewController的上邊緣到遮擋內容的Bar的下邊緣,那麼topLayoutGuide的top和bottom也就是這兩個邊緣了。

方法二:自動佈局的約束中,將Top Layout Guide.Bottom改成Top Layout Guide.Top。

這兩個方法達到的效果是同樣的,都是讓Label之內容ViewController的上邊緣進行約束,也就不會有變化了。Demo中沒有這個問題,是由於Demo沒有使用Autolayout。

可是也正是如此,兩個方法都不完美。內容ViewController是動態加載並嵌入到UIPageViewController中的,而topLayoutGuide又是一個只讀屬性,不能嵌入到UIPageViewController以前進行設置。

完美的方法應該是在加載內容ViewController的同時,告知內容ViewController它將被嵌入到另外一個容器當中,而這個容器包含一個Status Bar,因此應該從新判斷topLayoutGuide的值,但遺憾的是目前尚未找到這種完美的解決方案。若是你知道,但願能告訴我,謝謝!

相關文章
相關標籤/搜索