美文网首页iOS View
iOS中的系统转场

iOS中的系统转场

作者: CaryaLiu | 来源:发表于2016-12-28 13:02 被阅读541次

    更好的阅读体验,请到个人博客阅读: iOS中的系统转场

    请忽略标题,😂,本文记录的是对下图所示的Kind, Presentation, Transition的理解:

    iOS系统转场

    目录如下:

    1. Size Classes
    2. Kind转场类型

    <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,则

    1. presenting view controller, 是上述场景中的A view controller, 它会负责展示另外一个view controller
    2. 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 controllerpresenting that view controller on screen的过程中解耦,ViewController不需要知道它是嵌入到UINavigationController中或者是UISplitViewController中,都可以调用此方法来展示到屏幕上。UISplitViewControllerUINavigationController重写了该方法,使其能够根据自身设计来处理展现过程。例如,UINavigationController重写了该方法,并使用该方法来push viewcontrollernavigation stack中。

    该方法的默认实现会调用targetViewControllerForAction:sender:view controller层级中找到重写该方法的对象,然后调用该对象的此方法,使其能够以适当的方式来展现view controller。 如果targetViewControllerForAction:sender:方法返回nil,此方法会使用windowroot view controller来模态显示vc

    你可以在自定义view controller中重写该方法来展示vc,你的实现应该在regularcompact环境中做好适配。

    官方文档

    <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 controllerpresenting that view controller on screen的过程中解耦,ViewController不需要知道它是嵌入到UINavigationController中或者是UISplitViewController中,都可以调用此方法来展示到屏幕上。在regular环境,UISplitViewController重写了该方法,将vcdetail view controller的方式加载;在compact环境,split view controller的该方法实现是调用show(_:sender:)方法。

    show(_:sender:)相同:该方法的默认实现会调用targetViewControllerForAction:sender:view controller层级中找到重写该方法的对象,然后调用该对象的此方法,使其能够以适当的方式来展现view controller。 如果targetViewControllerForAction:sender:方法返回nil,此方法会使用windowroot view controller来模态显示vc

    你可以在自定义view controller中重载此方法来展示vc,使用此方法来将vc展现在secondary context中,例如,一个容器view controller可能会使用此方法来替换第二子控制器,你的实现应该为regularcompact环境做好适配.

    官方文档

    <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 controllerview大小。对于大多数的presentation styles,最终视图会以presented view controllermodalTransitionStyle属性设定的转场样式动画来显示到屏幕上。对于自定义的presentations, 视图会以presented view controllertransitioning delegate中要求的动画来展示。对于current context presentations,视图可能会是以当前view controllertransition style来显示到屏幕上,这种情况稍后会再次提到。

    注意: completion闭包是在presented view controllerviewDidAppear:的方法调用完成后才会调用。

    官方文档

    接下来聊聊present modally类型下的presentation style.

    <h3 id="presentation-style">Presentation Styles</h3>

    view controllerpresentation style控制其在屏幕上的显示。UIKit定义了多种标准的presentation styles, 每一种都有特定的UI展示和用途。当然,你也可以自定义presentation styles。当设计你的app时,根据当前的使用场景选择最合适的presentaion style, 然后设置presented view controllermodalPresentationStyle属性值为对应的常量值。

    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 controllerpresents右上角的蓝色view controller,对于某些presentation styles, UIKit会在两个view controller之间插入dimming view

    iOS默认转场动画类型

    经过测试,Partial Curl转场只有在PresentationFull 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 controllerpreferredContentSize,将视图大小设置为期望的大小;
    • presented view controllerpopoverPresentationController属性中获取关联的UIPopoverPresentationController对象,然后设置该对象的锚点。设置锚点可从如下两种方式中任选一种:
      • 设置barButtonItem属性值为一个bar button item;
      • 设置sourceViewsourceRect属性值为视图中的特定区域;

    你可以使用UIPopoverPresentationController对象来修改popover最终绘制出来的效果。popover presentation controller同样也支持使用一个delegate对象来监听presentation过程以做出对应的响应。例如,你可以使用该delegate对象来监听popoverappears, disappears, 或者repositioned on the screen事件,以做出对应的响应。关于该对象的更多信息,请参考: UIPopoverPresentationController Class Reference

    UIModalPresentationPopover样式会以浮层的形式显示view controller.Popovers可用来显示一些额外信息,或者,是当前聚焦或者选中对象关联的对象列表。在horizontally regular环境,弹出的浮层只会覆盖屏幕的一部分,如下图所示。在horizontally compact环境,popovers会默认适配为UIModalPresentationOverFullScreen样式。在浮层以外的区域点击则会自动使浮层消失。

    The popover presentation styleThe popover presentation style

    由于popovershorizontally compact环境下会自动适配为full-screen presentations,你需要编辑你的浮层代码以处理这种适配。在full-screen模式下,你需要一种方式来使presented popover消失。你可以添加一个按钮,将popover嵌入到可dismissible的容器视图控制器中,或者是修改该适配行为。

    相关文章

      网友评论

        本文标题:iOS中的系统转场

        本文链接:https://www.haomeiwen.com/subject/nlsyvttx.html