更好的阅读体验,请到个人博客阅读: iOS中的系统转场
请忽略标题,😂,本文记录的是对下图所示的Kind, Presentation, Transition的理解:
iOS系统转场目录如下:
<h1 id="size-classes">Size Classes</h1>
开始之前,先来了解一下Size Classes, 从iOS8.0开始引入了Size Classes的概念来对屏幕进行分类:把各个设备屏幕以及它们的屏幕旋转状态都抽象成屏幕Size的变化,下表是不同尺寸设备屏幕对Size Classes的约定。
Device | Portrait | Landscape |
---|---|---|
iPad (all)</br>iPad Mini | Vertical size class: Regular</br>Horizontal size class: Regular | Vertical size class: Regular</br>Horizontal size class: Regular |
iPhone 6 Plus | Vertical size class: Regular</br>Horizontal size class: Compact | Vertical size class: Compact</br>Horizontal size class: Regular |
iPhone 6 | Vertical size class: Regular</br>Horizontal size class: Compact | Vertical size class: Compact</br>Horizontal size class: Compact |
iPhone 5s</br>iPhone 5c</br>iPhone 5 | Vertical size class: Regular</br>Horizontal size class: Compact | Vertical size class: Compact</br>Horizontal size class: Compact |
iPhone 4s | Vertical size class: Regular</br>Horizontal size class: Compact | Vertical size class: Compact</br>Horizontal size class: Compact |
宽(正常,任意, 紧凑),高(正常,任意, 紧凑),3 x 3 共 9 种 Size,每种 Size 都可以设置特定的一套布局,如果不特殊指定,默认是在(宽任意,高任意)模式下设置,且其他 8 种布局继承它。对于Size Classes,可以看看博客: iOS8 Size Classes初探
<h1 id="presentation-kind">Kind-转场类型</h1>
先说明一下两个名词,假如view controller A模态展示了view controller B,则
- presenting view controller, 是上述场景中的A view controller, 它会负责展示另外一个view controller;
- presented view controller, 是上述场景中的B view controller,它是由其它控制器展示出来的view controller。
下图是Xcode8.0转场Kind的设置选项,可以看到系统默认的类型有四种,Show, Show Detail, Present Modally, Present As Popover。
转场类型<h2 id="presentation-kind-show">Show</h2>
Presents a view controller in a primary context.
func show(_ vc: UIViewController, sender: Any?)
使用该方法可以将display view controller从presenting that view controller on screen的过程中解耦,ViewController不需要知道它是嵌入到UINavigationController中或者是UISplitViewController中,都可以调用此方法来展示到屏幕上。UISplitViewController和UINavigationController重写了该方法,使其能够根据自身设计来处理展现过程。例如,UINavigationController重写了该方法,并使用该方法来push viewcontroller到navigation stack中。
该方法的默认实现会调用targetViewControllerForAction:sender:在view controller层级中找到重写该方法的对象,然后调用该对象的此方法,使其能够以适当的方式来展现view controller。 如果targetViewControllerForAction:sender:方法返回nil,此方法会使用window的root view controller来模态显示vc。
你可以在自定义view controller中重写该方法来展示vc,你的实现应该在regular和compact环境中做好适配。
<h2 id="presentation-kind-showdetail">Show Detail</h2>
Presents a view controller in a secondary (or detail)�� context.
func showDetailViewController(_ vc: UIViewController, sender: Any?)
该方法特点同Show类似:使用该方法可以将display view controller从presenting that view controller on screen的过程中解耦,ViewController不需要知道它是嵌入到UINavigationController中或者是UISplitViewController中,都可以调用此方法来展示到屏幕上。在regular环境,UISplitViewController重写了该方法,将vc以detail view controller的方式加载;在compact环境,split view controller的该方法实现是调用show(_:sender:)
方法。
同show(_:sender:)
相同:该方法的默认实现会调用targetViewControllerForAction:sender:在view controller层级中找到重写该方法的对象,然后调用该对象的此方法,使其能够以适当的方式来展现view controller。 如果targetViewControllerForAction:sender:方法返回nil,此方法会使用window的root view controller来模态显示vc。
你可以在自定义view controller中重载此方法来展示vc,使用此方法来将vc展现在secondary context中,例如,一个容器view controller可能会使用此方法来替换第二子控制器,你的实现应该为regular和compact环境做好适配.
<h2 id="presentation-kind-present-modally">Present Modally</h2>
Presents a view controller modally.
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion;
在horizontally regular的环境,view controller会以modalPresentationStyle属性设定的样式进行展现。在horizontally compact环境,view controller默认会以全屏的方式进行展现。对于viewControllerToPresent关联的presentation controller, 如果你实现了其adaptive delegate方法,则可以动态修改presentation style。
调用该方法的对象不一定是处理该presentation的对象。每一个presentation style会有不同的规则来处理其行为。例如,full-screen presentation必须由自身覆盖了整个屏幕的view controller来处理。如果调用该方法的当前view controlelr不能满足该要求,则它会沿着view controller的层级向上传递给最近的父控制器,由其父控制器来负责处理或者继续转发该请求。
在展现view controller之前,该方法会基于presentation style来设置presented view controller的view大小。对于大多数的presentation styles,最终视图会以presented view controller的modalTransitionStyle属性设定的转场样式动画来显示到屏幕上。对于自定义的presentations, 视图会以presented view controller的transitioning delegate中要求的动画来展示。对于current context presentations,视图可能会是以当前view controller的transition style来显示到屏幕上,这种情况稍后会再次提到。
注意: completion闭包是在presented view controller的viewDidAppear:的方法调用完成后才会调用。
接下来聊聊present modally类型下的presentation style.
<h3 id="presentation-style">Presentation Styles</h3>
view controller的presentation style控制其在屏幕上的显示。UIKit定义了多种标准的presentation styles, 每一种都有特定的UI展示和用途。当然,你也可以自定义presentation styles。当设计你的app时,根据当前的使用场景选择最合适的presentaion style, 然后设置presented view controller的modalPresentationStyle属性值为对应的常量值。
modalPresentationStyle:
The presentation style determines how a modally presented view controller is displayed onscreen. In a horizontally compact environment, modal view controllers are always presented full-screen. In a horizontally regular environment, there are several different presentation options. For a list of possible presentation styles, and their compatibility with the available transition styles, see the UIModalPresentationStyle constant descriptions.
UIModalPresentationStyle的枚举值定义如下:
public enum UIModalPresentationStyle : Int {
case fullScreen
@available(iOS 3.2, *)
case pageSheet
@available(iOS 3.2, *)
case formSheet
@available(iOS 3.2, *)
case currentContext
@available(iOS 7.0, *)
case custom
@available(iOS 8.0, *)
case overFullScreen
@available(iOS 8.0, *)
case overCurrentContext
@available(iOS 8.0, *)
case popover
@available(iOS 7.0, *)
case none
}
由于popover需要进行特殊处理,在Xcode中,Presentation处仅有如下图所示的设置:
Presentation设置值对以上枚举值进行大体分类: full-screen presentation styles, popover style, current context styles, custom presentation styles。其中:
- full-screen presentation styles对应枚举值fullScreen, pageSheet, formSheet, overFullScreen;
- popover style对应枚举值popover;
- current context styles对应枚举值currentContext, overCurrentContext。
先看看full-screen presentation styles。
<h4 id="full-screen-presentation">Full-Screen Presentation Styles</h4>
Full screen presentation styles cover the entire screen, preventing interactions with the underlying content. In a horizontally regular environment, only one of the full-screen styles covers the underlying content completely. The rest incorporate dimming views or transparency to allow portions of the underlying view controller to show through. In a horizontally compact environment, full-screen presentations automatically adapt to the UIModalPresentationFullScreen style and cover all of the underlying content.
full screen presentation styles会覆盖设备的整个屏幕,阻止用户与底部内容进行交互。在horizontally regular环境,full screen presentation styles中只有一种类型(UIModalPresentationFullScreen)会完全覆盖住底部的内容,其余的类型会结合透明或者黑色半透明的视图来使底部的部分内容显示出来。在horizontally compact环境,所有的full screen presentation styles会自动适配为UIModalPresentationFullScreen类型并覆盖底部的所有内容。
下图是在horizontally regular环境下fullScreen, pageSheet, formSheet样式下的显示效果。图中,左上角的绿色view controller会presents右上角的蓝色view controller,对于某些presentation styles, UIKit会在两个view controller之间插入dimming view。
iOS默认转场动画类型经过测试,Partial Curl转场只有在Presentation为Full Screen时才会有效,其余presentation styles会导致crash,不知道是我使用的方式不对或者是其它原因,请指教。
<h2 id="presenting-popover">Presenting a View Controller in a Popover</h2>
同上,这种方式也是使用api:
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion;
来展现视图。与上不同的是,popover的展现方式还需要额外的配置。在设置 model presentation style值为UIModalPresentationPopover之后,配置如下与popover相关的属性值:
- 设置presented view controller的preferredContentSize,将视图大小设置为期望的大小;
- 从presented view controller的popoverPresentationController属性中获取关联的UIPopoverPresentationController对象,然后设置该对象的锚点。设置锚点可从如下两种方式中任选一种:
- 设置barButtonItem属性值为一个bar button item;
- 设置sourceView和sourceRect属性值为视图中的特定区域;
你可以使用UIPopoverPresentationController对象来修改popover最终绘制出来的效果。popover presentation controller同样也支持使用一个delegate对象来监听presentation过程以做出对应的响应。例如,你可以使用该delegate对象来监听popover的appears, disappears, 或者repositioned on the screen事件,以做出对应的响应。关于该对象的更多信息,请参考: UIPopoverPresentationController Class Reference
UIModalPresentationPopover样式会以浮层的形式显示view controller.Popovers可用来显示一些额外信息,或者,是当前聚焦或者选中对象关联的对象列表。在horizontally regular环境,弹出的浮层只会覆盖屏幕的一部分,如下图所示。在horizontally compact环境,popovers会默认适配为UIModalPresentationOverFullScreen样式。在浮层以外的区域点击则会自动使浮层消失。
The popover presentation style由于popovers在horizontally compact环境下会自动适配为full-screen presentations,你需要编辑你的浮层代码以处理这种适配。在full-screen模式下,你需要一种方式来使presented popover消失。你可以添加一个按钮,将popover嵌入到可dismissible的容器视图控制器中,或者是修改该适配行为。
网友评论