UISplitViewController
類是一個容器視圖控制器,它顯示一個master-detail
界面(主界面、詳細界面)。在master-detail
界面中,主視圖控制器(master
)的變化會驅動輔助視圖控制器(detail
)變化。 兩個視圖控制器(master
控制器、detail
控制器)的排列是可以控制的, 他們可以同時顯示或者一次只顯示一個。UISplitViewController
在iOS3.2的時候就有了,只不過iOS8才開始支持iPhone(比如在iPhone6 plus上顯示視圖和iPad很相似了)。
Overview
在構建應用程序的用戶界面時,split?View?Controller
通常是應用程序窗口(window)的根視圖控制器。split?View?Controller
沒有明顯的外觀,它的外觀基本上是由它的子視圖控制器(master、detail控制器)決定的。 你可以以Interface Builder
的方式或者代碼的方式構建該控制器。
Note
你不能把split?View?Controller
push到navigationController
的棧中
盡管在一些容器視圖控制器中,把split?View?Controller
當做子控制器這個操作是可行的,但是大多數情況不允許這么做。再次聲明,split?View?Controller
通常配置為window的root控制器。 有關實現界面的方法的提示和指導,請參閱iOS Human Interface Guidelines。
split?View?Controller
基于可用空間確定其子視圖控制器的排列:
在水平規則的環境中,split?View?Controller
盡可能并排地呈現其視圖控制器(同時并排地顯示master、detail控制器)。
在水平緊湊的環境中,split?View?Controller
的行為更像導航控制器,最初顯示主視圖控制器,并根據需要push
或pop
第二個控制器。
當顯示在屏幕上時,split?View?Controller
使用其"代理對象"(Delegation object)來管理其子視圖控制器的顯示。具體參考此處:UISplit?View?Controller?Delegate
Configuring the Appearance of the Split View Interface
split?View?Controller顯示的視圖配置由當前顯示模式(displayMode
)決定。 配置displayMode需要用到preferredDisplayMode
屬性。
分割視圖控制器盡力尊重您指定的顯示模式,但由于空間限制,可能無法視覺上適應該模式。 例如,分割視圖控制器不能在水平緊湊的環境中并排顯示其子視圖控制器。
下面列出了可用的顯示模式,并描述了視圖控制器如何布置在屏幕上。 該表還列出了用于請求指定顯示模式的常量。
-
Side-by-side
同時顯示全部控制器。主視圖控制器顯示在左側,通常比次視圖控制器更窄。可以使用preferred?Primary?Column?Width?Fraction屬性來控制寬度.
當is?Collapsed
屬性為true的時候,這個模式不會顯示。在折疊的界面(collapsed interface)時,一次只能看到一個試圖控制器。
這個模式由枚舉中all?Visible
表示。
-
Hidden:
次視圖控制器顯示在屏幕上,主視圖控制器處于關閉屏幕。
要顯示主視圖控制器,您必須以模態顯示(present it modally)或更改顯示模式(change the display mode)。
該模式由枚舉中的primary?Hidden
表示。
-
Overlay
次視圖控制器在屏幕上,主視圖控制器分層在其上。 在此模式下,主視圖控制器部分地遮擋了次視圖控制器(如下圖:右側的控制器一部分被遮擋了)。
此模式由primary?Overlay
表示。
當設置完preferredDisplayMode
后,split?View?Controller會自動更新,并在displayMode
屬性中反映實際的顯示模式。
您可以隨時更改首選顯示模式,這樣做會導致split?View?Controller相應地進行自我調整 。
分割視圖控制器還安裝內置手勢識別器,讓用戶使用滑動來更改顯示模式。您可以通過將presentsWithGesture
屬性設置為false來抑制此手勢識別器。
display?Mode?Button?Item
display?Mode?Button?Item
方法返回一個特殊的barButtonItem
,用于改變displayMode
,你可以將其包含在應用程序的用戶界面中。
你需要做的是將這個
barButtonItem
添加到界面中相應的navigation bar
或toolbar
。
當它點擊被的時候,按鈕會向splitViewController發送一個消息,告訴它改變當前的displayMode
。
關于改變的結果取決于代理方法中的target?Display?Mode?For?Action(in:?)
方法(ps: Objctve-C中對應targetDisplayModeForActionInSplitViewController:
)。次方法缺省值的為Automatic
//設置舉例
// Called by the gesture AND barButtonItem to determine what they will set the display mode to (and what the displayModeButtonItem's appearance will be.) Return UISplitViewControllerDisplayModeAutomatic to get the default behavior.
- (UISplitViewControllerDisplayMode)targetDisplayModeForActionInSplitViewController:(UISplitViewController *)svc {
if (self.displayMode == UISplitViewControllerDisplayModePrimaryHidden) {
return UISplitViewControllerDisplayModeAllVisible;
}else if (self.displayMode == UISplitViewControllerDisplayModeAllVisible){
return UISplitViewControllerDisplayModePrimaryHidden;
}else{ //UISplitViewControllerDisplayModePrimaryOverlay
return UISplitViewControllerDisplayModePrimaryHidden;
}
//這個是缺省值。 默認: 展開為`Overlay`. 隱藏為`Hidden`
//return UISplitViewControllerDisplayModeAutomatic;
}
上述代理如果設置返回的是UISplitViewControllerDisplayModeAutomatic
或者干脆沒實現這個代理方法,視圖控制器會根據當前屏幕大小選擇合適的模式。 例如,在豎屏的iPad上,控制器在hidden和overlay模式之間切換。
切換模式也可以通過手勢來進行,手勢也可以通過代理方法來確定要使用的顯示模式。
Changing Child View Controllers in a Split View Interface(改變子視圖控制器)
當設計一個splitViewController的時候,當然如果主視圖和輔助視圖都不改變是最好的。
常見的技術是在主視圖和輔助視圖都是導航控制器(navigationController)控制的,然后可以根據實際的需要進行控制器的push
或者pop
操作.
如果需要更改主視圖控制器或輔助視圖控制器,建議您使用show(_:?sender:?)
和show?Detail?View?Controller(_:?sender:?)
方法。使用這些方法(而不是直接修改controllers
屬性)使分割視圖控制器以最適合當前顯示模式和size class的方式呈現指定的視圖控制器。
splitViewController知道如何以更直觀的方式調整界面。它甚至可以與其他容器視圖控制器(如導航控制器)一起使用來呈現視圖控制器。舉個有點特殊的例子,在比較緊湊(compact
)的環境中(比如iPhone 6plus的橫屏狀態),開始顯示的控制器A(輔助視圖)是一個導航控制器。這時候調用show?Detail?View?Controller(_:?sender:?)
方法并不會替換掉視圖控制器A。相反,視圖控制器A將目標控制器push到其導航堆棧。
Collapsing and Expanding the Split View Interface
splitViewController進行展開和收齊的時候,它的size class
在水平方向的regular
和compact
間切換。 在切換過程中,splitViewController會改變子視圖控制器的顯示方式.
當從水平方向regular
轉換到compact
時,splitViewController”收起“后顯示一個控制器。
當從水平方向compact
轉換到regular
時,splitViewController會根據設定的displayMode
屏幕”展開“顯示一個或多個控制器.
收起 (collapsing process)
當界面轉換到“收起"時,分割視圖控制器與其代理一起管理轉換。在”收起“結束時,splitViewController通常只顯示主視圖控制器了。
你可以在代理中實現primary?View?Controller(for?Collapsing:?)
方法來變此行為。您可以使用該方法來指定次視圖控制器或完全不同的視圖控制器 - 也許那個控制器更適合在水平方向compact
的環境中顯示。
如果相對控制器和視圖層次進行額外調整,你可以在代理中實現split?View?Controller(_:?collapse?Secondary:?onto:?)
方法。
展開 (expansion process)
展開是收起的相反的過程。這一過程會詢問delegate哪個控制器將成為主視圖控制器(primary view controller)并且提供給delegate機會去執行transition變換。
如果你實現了"收起"的代理方法,那么同樣你也應該為"展開"實現primary?View?Controller(for?Expanding:?)
和split?View?Controller(_:?separate?Secondary?From:?)
方法。
如果沒實現“收起”和“展開”的任何代理方法,那也沒關系。splitViewController提供了收起/展開的缺省值。
關于收起(collapse)、展開(expand)的更多信息,請查看UISplit?View?Controller?Delegate.
Message Forwarding to Its Child View Controllers
splitViewController對window和子控制器(child view controllers)進行了協調。 因此所有到子控制的所有消息都會流經splitViewController.
這通常可以預期,消息的流程應該比較直觀。 例如,僅當相應的子視圖控制器實際出現在屏幕上時才會發送查看外觀顯示或消失的消息。
State Preservation
在iOS6或者更高版本上,如果你給定了splitViewController的restoration?Identifier屬性值。 那么它將會保存具有有效恢復標識符(valid restoration identifier)的所有子控制器。
在程序下一次啟動時,splitViewController將會回復到之前的狀態。splitViewController的子視圖控制器可以使用相同的恢復標識符。splitViewController自動存儲附加信息,以確保每個子控制器的恢復路徑是唯一的。
有關狀態保存和恢復的工作原理的更多信息,請參閱App Programming Guide for iOS。
參考內容
https://developer.apple.com/reference/uikit/uisplitviewcontroller
http://nshipster.cn/uisplitviewcontroller/