UIModalPresentationStyle 各種型別的區別

Natai發表於2019-04-17

UIViewController有個屬性modalPresentationStyle,它決定了當前控制器 present 出的下一控制器的展示方式。

官方文件對這些效果有比較詳細的介紹,這裡寫個 demo 幫助理解,demo 在模擬器上執行可能會有一點卡頓,真機沒有影響。

預備知識

presenting、presented viewController

presentingViewController指的是 present 出當前控制器的控制器。

presentedViewController指被當前控制器 present 出的控制器。

Size Class

對於各種常見情況的 Size Class 如下幾張圖片所示:

iPhonePlus的SizeClass
iPhonePlus的SizeClass

普通iPhone的SizeClass
普通iPhone的SizeClass

全屏iPad的SizeClass
全屏iPad的SizeClass

UIModalPresentationStyle

enum UIModalPresentationStyle : Int {
    case fullScreen
    case pageSheet
    case formSheet
    case currentContext
    case custom
    case overFullScreen
    case overCurrentContext
    case popover
    case none
}
複製程式碼

fullScreen

  • 在各種 Size Class 情況下都是全屏展示
  • 執行 present 操作的控制器的view和它的subViews,在 present 完成後都會被從當前檢視層級移除

fullScreen
fullScreen

對於水平方向為 compact 的情況,不管用哪種 style 推出其他控制器,presentedViewController都是以fullScreen方式展示。所以剩下的所有型別,都只針對水平方向為 regular 論述。

pageSheet

  • 被推出檢視部分的遮蓋下層檢視
  • 其寬度總是為該裝置豎屏時候的寬度(不可變),高度則為當前裝置方向的螢幕高度(可變,其實還要去掉狀態列的高度)

pageSheet豎屏
pageSheet豎屏

pageSheet橫屏
pageSheet橫屏

formSheet

  • 被推出檢視大小比螢幕的小,且總是居中顯示
  • 在橫屏時,如果彈出了鍵盤,檢視位置會跟著上移
  • 可以設定被推出檢視的preferredContentSize來設定它的大小

formSheet豎屏
formSheet豎屏

formSheet橫屏
formSheet橫屏

這裡設定了preferredContentSize = CGSize(width: 200, height: 200)

currentContext

  • 可以用在 iPadUISplitViewController中,指定單獨覆蓋螢幕單側的控制器;popover方式展示的控制器,再用該方式 present 出下一檢視
  • 在執行 present 操作的控制器的控制器層級中往上查詢,如果某個控制器的definesPresentationContext == true則它來 present,假如沒有一個為true,那麼則由 window.rootController來 present
  • 執行 present 操作的控制器的view和它的subViews,在 present 完成後都會被從當前檢視層級移除

definesPresentationContext預設為false,系統提供的一些像UINavigationController的控制器,其預設值為true。它的定義為:

A Boolean value that indicates whether this view controller's view is covered when the view controller or one of its descendants presents a view controller.

對於以currentContext方式推出的檢視,如果它的presentedViewController是一個popover,那麼推出該檢視的modalTransitionStyle不能是partialCurl,否則會引起崩潰。

currentContext豎屏
currentContext豎屏

currentContext橫屏
currentContext橫屏

currentContextInPopover
currentContextInPopover

custom

A custom view presentation style that is managed by a custom presentation controller and one or more custom animator objects.

詳細介紹在下篇文章中進行。

overFullScreen

基本和fullScreen一致。只是 present 完成後,不會移除執行 present 操作的控制器的view和它的subViews。如果presentedViewController.view是有透明度的,底層檢視就可以得以顯示。

overFullScreen
overFullScreen

overCurrentContext

基本和currentContext一致。只是 present 完成後,不會移除執行 present 操作的控制器的view和它的subViews。如果presentedViewController.view是有透明度的,底層檢視就可以得以顯示。

overCurrentContext
overCurrentContext

popover

  • 在 iPad 上用popover的方式顯示;在 iPhone 上預設用fullScreen方式顯示,但是在 iOS8 後可以設定成popover的方式,在none中會進行解釋
  • 預設情況下,點選灰色的背景popover會直接消失,通過presentedViewController.popoverPresentationController?.passthroughViews可以配置灰色背景的哪些檢視區域可以點選

UIPopoverPresentationController的定義:

An object that manages the display of content in a popover.

當檢視被用popover方式 present 的時候,總有一個popoverPresentationController的例項來管理呈現的行為。

popover
popover

none

  • 該列舉值不可以直接賦值給modalPresentationStyle
  • popoverPresentationController會呼叫它delegate的方法來配置popover的檢視,none只能用在adaptivePresentationStyle(for:)代理方法中返回,告訴popoverPresentationController不要適配presentedViewController,這樣在 iPhone 中也可以用popover的樣式展示了

none
none

相關文章