跳转至

Slice 基础与页面开发

本文档以 src/application/wearable/nativeapp/nativeui/helloworldpage 为例,说明 OpenHarmony Native Slice 应用的框架背景、快速跑通 Hello World、工程代码结构、快速开发流程、页面注册链路、页面实现和常见开发问题,帮助开发者基于现有 NativeApp 工程创建自己的 Native demo。


OpenHarmony Native Slice背景知识

本章介绍 Native Slice 应用的核心背景,包括 NativeAbilityFwk 框架、Slice 应用开发模型、Slice 跳转机制和 SlicePage 跳转机制。开发者应先理解这些概念,再进入 HelloWorld Native Demo 的创建和代码走读。

NativeAbilityFwk

NativeAbilityFwk介绍

NativeAbilityFwk子系统是开发Native Slice应用的框架,包括Slice MVP架构、生命周期管理、转场动效、最近访问记录管理,是基于穿戴产品特点从鸿蒙原生Native应用框架演化而来。

Ability分Native Ability以及JS Ability两种,相关基础概念如下:

  • Native Ability,用来管理Native Slice应用,有且仅有一个实例。

    • Slice,用来表示一个Native应用,拥有自己的生命周期;它与Native应用是等价的概念。

    • SlicePage,用来表示Slice内部的某一个页面,拥有自己的生命周期。如果Slice内部只有一个页面,可以不使用SlicePage。比如包含多个卡片的一级页面,借助UICardPage(请参考《UIKit开发指南》中的“UICrossView”章节)可表示其中一个卡片,而单个卡片并不能被视作为一个页面。另外,也可以将同一个SlicePage注册(请参考“创建并注册SlicePage”)到不同的Slice中,这样可以实现一个页面在不同Slice间的共享。

    • UIFragment,用来表示一块显示内容,拥有自己的生命周期。借助它可以实现指定区域显示内容在不同页面间的共享,也可以实现指定区域显示内容的动态替换。比如:一级页面中的卡片与卡片应用间显示内容的共享(参考示例代码中的指南针卡片与应用);应用列表不同风格显示内容的动态切换(参考《UIKit开发指南》中的“桌面样式”章节)。

      指南针共享内容代码:/src/application/wearable/nativeapp/nativeui/compass/src/CompassFragment.cpp

  • JS Ability,为JS应用的入口,一个应用对应一个实例,用于管理JS Page,JS Page使用JS+HML+CSS编程,具体请参考《OpenHarmony JS应用开发用户指南》

Native Ability的框架如图1所示,可以分为Framework和App两层。

图 1 Native Ability框架图

Native-Ability框架图

  • Framework层,是Native Ability应用开发的框架基础,模块具体职能如下:

    • Launcher:负责Native应用资源和数据的初始化,以及Native Slice的注册。

    • NativeAbility:负责Native Slice的创建以及生命周期的管理;并对外提供Slice和SlicePage跳转的接口。

    • TransitionCallback:转场动效的对外接口,当前在“application\wearable\nativeabilityfwk\src\transition”目录中已提供示例,开发者可以新增定制动效。

    • PageTransitionManager:负责JS应用、Native Slice应用间转场动效的管理。

    • SlicePageManager:负责Slice应用内部SlicePage的创建以及生命周期的管理。

    • RecentManager:负责记录和截图保存用户最近访问过的JS应用、Native Slice应用。

  • App层,即应用层,当前在“application\wearable\nativeapp”目录中已提供示例,开发者可以实现自己的Ability Slice、Slice内部的Slice Page、以及UIFragment。

    • Slice开发可以借助MVP(可参考“Slice MVP架构概述”)架构模式进行开发。

    • 如果Slice中的页面较多,可以使用SlicePage,这样页面的管理和切换可以交由Framework层来处理;如果Slice中仅有一个页面,可以不使用SlicePage。

Slice应用开发

Slice MVP架构概述

一个完整的Slice页面使用MVP架构实现,有Model、View和Presenter三部分,其中Model与View原则上是解耦的,它们的职责如下:

  • M:Model,管理业务模型的数据和业务逻辑。

  • V:View,管理显示界面以及与用户的交互。如果Slice中包含SlicePage,SlicePage需要承担View的角色,可参考SettingView与SettingMainPage。

  • P:Presenter,负责完成View与Model之间的交互,数据变化触发更新界面;用户交互触发数据更新。如果一个应用包含较多的SlicePage,可以考虑将业务逻辑移到SlicePage中处理,即SlicePage可以承担Presenter的角色,可参考SettingPresenter与SettingMainPage。

总之,MVP是一个比较好的解耦设计,但是在代码简洁与解耦之间,开发者需要做好权衡。

Model

Model用于管理数据,通常以单例方式存在,以便在多Slice间更简单地共享数据。

View

View继承自“View.h”,用于视图构建和显示。“View.h”生命周期需要用户实现的接口如表1所示。

表 1 View.h生命周期接口

接口名

说明

OnStart(data)

启动Slice并且在动画(如果有)开始前调用,支撑传递数据,逻辑实现请参考“Slice生命周期实现建议”章节。

OnStart

同上,但不建议使用。

OnStop

在当前页面不可见并且销毁的时候调用,逻辑实现建议参考“Slice生命周期实现建议”章节。

说明:

OnStart和OnStart(data)都会调用,无论是否真正有data,都推荐使用OnStart(data)。

View中的RootView控件树嵌套层级如下:

图 1 MVP RootView控件树图

MVP-RootView控件树图

须知:

不建议将自定义控件CustomView[x]直接添加到RootView中,因为转场动效基于RootContainer本身或者截图进行显示,如果将CustomView[x]直接添加到RootView中,则会导致转场动效的显示出现错乱。

Presenter

Presenter继承自“Presenter.h”,用于处理数据与视图之间的交互。“Presenter.h”生命周期需要用户实现的接口如表1所示。

表 1 Presenter.h生命周期接口

接口名

说明

OnStart(data)

启动Slice并且在动画(如果有)开始前调用,在View::OnStart之后调用,支撑传递数据,逻辑实现建议参考“Slice生命周期实现建议”章节。

OnStart

同上,但不建议使用。

OnResume

动画(如果有)结束并且页面(恢复)可见时调用,逻辑实现建议参考“Slice生命周期实现建议”章节。

OnPause

页面进入后台时调用,逻辑实现建议参考“Slice生命周期实现建议”章节。

OnStop

页面不可见并且销毁时调用,逻辑实现建议参考“Slice生命周期实现建议”章节。

Slice开发

创建并注册Slice
  1. 创建Slice

    创建Slice有IDE GUI工程自动创建和手动创建两种方式,相比于手动创建,IDE GUI工程自动创建Slice优势如下:

    • 支持通过拖拉点拽边界UI界面。

    • 自动创建会自动生成View、Presenter、Model的代码。

    • 自动创建会生成静态注册的代码,并且注册的SliceId在[VIEW_MAX_INTER_ARRY_APP, VIEW_MAX_INTER_APP]之间。

    IDE GUI工程自动创建Slice,可以参考《HiSpark Studio for VS Code 使用指南》中的“GUI工程创建与使用”,本文不再赘述。

    手动创建Slice,需要手动添加View、Presenter、Model的代码,并手动添加Slice静态注册代码,具体可参考nativeapp目录下的示例。如果Slice内部有SlicePage,为了代码简洁性,View和Presenter可以简化,并将相关逻辑放到SlicePage中。

  2. 静态注册Slice

    静态注册Slice支持如下两种方式:

    • 普通注册:借助宏REGIST_SLICE完成,该方式注册的Slice可以借助Slice id跳转进入Slice页面,但是不会在菜单中显示该Slice的图标,注册方式为:REGIST_SLICE(id, V, P)

    • 菜单注册:借助宏REGIST_MENU或者REGIST_MENU_EXT完成,该方式注册的应用不仅可以借助Slice id进行跳转进入Slice页面,也可以在菜单中显示该Slice的图标,注册方式为:

      REGIST_MENU(id, V, P, icon, iconHexagon, label):不支持多语言以及图标打包。

      REGIST_MENU_EXT(item,V, P):支持多语言以及图标打包,方便开发者借助AppItem的构造方法进一步扩展。

    Slice 应用的注册顺序通过 ID 升序排序,如果用户期望改变菜单中 Slice 应用的排布顺序,可以在 ApplistModel.cpp 的 ResolvingJSAppItems 中定制排布顺序。

表 1 REGIST_SLICE参数说明

参数

说明

id

Slice的ID(必须大于0,0为无效值)。

V

对应的View文件的类名。

P

对应的Presenter文件的类名。

表 2 REGIST_MENU参数说明

参数

说明

id

Slice的ID(必须大于0,0为无效值)。

V

对应的View文件的类名。

P

对应的Presenter文件的类名。

icon

标准应用图标资源文件的路径。

iconHexagon

六边形应用图标资源文件的路径。

label

应用名。

表 3 REGIST_MENU_EXT参数说明

参数

说明

item

AppItem结构体对象。

V

对应的View文件的类名。

P

对应的Presenter文件的类名。

建议在“XXXPresent.cpp”中进行注册,具体可以参考图1

图 1 Slice注册示例图

Slice注册示例图

**图 1** Slice注册示例图

Slice生命周期实现建议

以Slice A转场到Slice B为例(不考虑转场动画),具体也可参考“Slice.h/View.h/Presenter.h”的注释。

  1. SliceA OnPause:Slice A进入Pause状态。

    Presenter::OnPause:建议暂停动画,清除焦点,清除输入事件监听。

  2. SliceA OnStop:Slice A进入Stop状态。

    View::OnStop/~View:建议销毁Slice A中自创建的控件资源。(系统会自动将自创建控件从rootContainer_中移除)

    Presenter::OnStop/~Presenter:建议销毁Slice A中的非控件资源。

  3. SliceB OnStart:Slice B进入Start状态。

    View()/View::OnStart:建议初始化控件资源,并借助接口GetRootContainer()将其添加到RootView控件树中。

    Presenter()/Presenter::OnStart:建议初始化非控件资源,基于Model非实时数据刷新已初始化的控件状态。

  4. SliceB OnResume:Slice B进入Resume状态。

    Presenter::OnResume:建议基于实时数据刷新控件状态、启动页面开场动画、获取焦点、设置输入事件监听等。

SlicePage开发

创建并注册SlicePage

首先,根据当前Slice内部页面的个数和实际业务诉求,决定是否使用SlicePage。即使只有一个页面,也可以使用SlicePage。

其次,如果创建SlicePage,需要新建一个继承于SlicePageBase的子类,并在该类的cpp文件中将SlicePage注册到Slice中。如前文所述,SlicePage可以同时承担View和Presenter的角色,具体可以参考实例SettingMainPage的实现。

注册SlicePage使用REGIST_SLICE_PAGE方法静态注册到指定的Slice中:REGIST_SLICE_PAGE(sliceId, pageId, V, isMainPage)

如果将同一个SlicePage注册到不同的应用中,那么这个页面就可以在两个不同的应用中共享使用。

表 1 REGIST_SLICE_PAGE参数说明

参数

说明

sliceId

Slice的ID(必须大于0,0为无效值)。

pageId

SlicePage的Id(必须大于0,0为无效值)。

V

对应的View文件的类名。

isMainPage

当前SlicePage是否为当前Slice的默认Page,即启动Slice是否默认启动到该页面。

SlicePage生命周期实现建议

以Slice内部由SlicePage A跳转到SlicePage B为例(不考虑动画):

  1. SlicePage A OnPause:SlicePage A进入Pause状态。如果支持缓存SlicePage A,则跳过2

    建议暂停SlicePage A中的动画,并清除输入事件监听。

  2. SlicePage A OnStop:SlicePage A进入Stop状态。

    建议销毁SlicePage A中自创建的控件资源。(系统会自动将自创建控件从pageContainer_中移除)

    为了代码简洁,可以承担Presenter角色销毁SlicePage A的非控件资源。

  3. SlicePage B OnStart:SlicePage B进入Start状态。

    建议初始化SlicePage B的控件资源,并借助接口GetSlicePageContainer()将其添加到RootView控件树中。

    为了代码简洁,可以承担Presenter角色初始化非控件资源,并基于Model非实时数据刷新已初始化的控件状态。

  4. SlicePage B OnResume:SlicePage B进入Resume状态。

    为了代码简洁,可以承担Presenter角色基于实时数据刷新控件状态、启动页面开场动画、获取焦点、设置输入事件监听等。

当由Slice A跳转到Slice B的指定SlicePage B时,SlicePage B的生命周期调用与SliceB Presenter生命周期调用保持一致。针对这个不同的场景,SlicePage的实现建议并无区别。

UIFragment开发

UIFragment介绍

UIFragment用来表示一块拥有自己生命周期的显示内容。与SlicePage类似,UIFragment同样拥有自己的根容器控件,将其添加到View、SlicePage或者UICradPage的根容器控件中就可以正常显示。

开发者需代码实现UIFragment的子类,并通过构造函数直接创建UIFragment子类的实例。创建UIFragment子类实例时如果指定了ID,则可以通过UIFragmentMananger借助该ID查找到该实例。

UIFragmentManager::GetInstance().GetFragmentById("id_name")

UIFragment不同生命周期的处理逻辑,一方面需要开发者自己实现,另一方面还需开发者在View、SlicePage或者UICardPage的生命周期主动触发调用。具体的生命周期变化时序以及生命周期调用函数可参考图1

为了保证代码的简洁性以及内聚性,UIFragment建议同时承担View和Presenter的角色。

图 1 UIFragment状态变化示意图

UIFragment状态变化示意图

表 1 UIFragment的接口说明

接口名

说明

UIFragment()

构造函数,不会注册到UIFragmentManager中。

UIFragment(const std::string& id)

带参数的构造函数,以key为id的方式注册到UIFragmentManager中。

virtual void OnCreateView(void* data)

待子类实现的protected虚函数,建议创建控件并将其添加到UIFragment根容器控件fragmentview_中。

virtual void OnResumeView()

待子类实现的protected虚函数,与Slice(Page) OnResume行为保持一致,建议设置输入监听,获取焦点以及启动动画等。

virtual void OnPauseView()

待子类实现的protected虚函数,与Slice(Page) OnPause行为保持一致,建议清除输入监听,清除焦点以及暂停动画等。

virtual void OnDestroyView()

待子类实现的protected虚函数,建议销毁控件。

void ResumeView()

外部调用函数,如果状态为INITIALZIED,会触发调用OnCreateView方法。

UIView* CreateView(void *data = nullptr)

外部调用函数,如果状态为CREATED,会触发调用OnCreateView方法。

void PauseView()

外部调用函数,如果状态为RESUMED,会触发调用OnCreateView方法。

void DestroyView()

外部调用函数,如果状态为CREATED|RESUMED,会触发调用OnCreateView方法。

UIView* GetFragmentView()

外部调用函数,用于获取UIFragment的根容器控件fragmentView_。

UIFragment使用场景

Slice跳转

Slice跳转方法说明

NativeAbility单例提供了两种Slice跳转的方法:

    void ChangeSlice(uint16_t targetSliceId, TransitionType type = TransitionType::TRANSITION_INVALID,

        uint16_t priority = gSliceDefaultPriority, bool enableSlideBack = false);

    void SwitchSlice(uint16_t sliceId, uint16_t pageId = gPageInvalid,

        TransitionType type =  TransitionType::TRANSITION_INVALID, bool enableSlideBack = false);



// 示例,直接跳转到应用列表

    NativeAbility::GetInstance().ChangeSlice(VIEW_APPLIST); // 方式1

    NativeAbility::GetInstance().SwitchSlice(VIEW_APPLIST); // 方式2
  • SwitchSlice方法:用于跳转到指定Slice的匹配pageId的SlicePage页面,如果pageId不指定,则跳转到Slice默认页面,等价于ChangeSlice方法。Slice如果无SlicePage,那么默认页面通过MVP中的View创建,否则为已经注册的默认SlicePage页面。

  • ChangeSlice方法:用于跳转到Slice的默认页面,其实现依赖于SwitchSlice方法。

无论是SwitchSlice还是ChangeSlice,在快速点击或者AT压力测试环境下,若当前存在未完成的跳转任务,则新的跳转动作将会缓存起来。等到当前的跳转任务执行完毕后再延迟执行缓存的跳转动作。

表 1 ChangeSlice参数说明

参数

说明

targetSliceId

目标Slice的ID。

type

切换动效类型,默认为TransitionType::TRANSITION_INVALID,即无动效。

priority

Slice优先级,默认值为4,当前未使用。

enableSlideBack

是否支持跟手返回,默认值为false。

表 2 SwitchSlice参数说明

参数

说明

sliceId

目标Slice的ID。

pageId

目标SlicePage的ID。

type

切换动效类型,默认为TransitionType::TRANSITION_INVALID,即无动效。

enableSlideBack

是否支持跟手返回,默认值为false。

支持Slice跳转动效

系统自带的Slice跳转动效

在头文件“TransitionType.h”中定义了系统自定的跳转动效类型,说明如表1所示。

表 1 默认动效跳转类型

type

说明

TRANSITION_INVALID

无动效。

TRANSITION_ZOOM

缩放动效(先缩小,后放大)。

TRANSITION_HEXAGONS

蜂窝菜单离场动效。

TRANSITION_BACK_TO_HEXAGONS

蜂窝菜单返场动效。

TRANSITION_ENTER_WATERFALL

瀑布流菜单入场动效。

TRANSITION_BACK_TO_WATERFALL

瀑布流菜单返场动效。

TRANSITION_WATERFALL

瀑布流菜单离场动效。

定制Slice跳转动效
  1. 在“TransitionType.h”下添加定制动效ID。

  2. 在transition目录下,新建定制动效类,该类继承TransitionCallback类并重写父类方法。

    表 1 TransitionCallback接口

    类型

    接口名

    说明

    变量

    duration_

    动效持续时间,不能在类中指定,需要在3中指定。

    enableCurrentSnapshot_

    当前页面是否截图,不能在类中指定,需要在3中指定。

    enableTargetSnapshot_

    跳转页面是否截图,不能在类中指定,需要在3中指定。

    函数

    1. virtual void OnTransitionStart(UIImageView current, UIImageView target)
    2. virtual void OnTransitionStart(UIImageView current, UIViewGroup target)
    3. virtual void OnTransitionStart(UIViewGroup current, UIImageView target)
    4. virtual void OnTransitionStart(UIViewGroup current, UIViewGroup target)

    动效开始调用,用于动效所需控件和状态初始化,四个函数分别对应如下场景:

    1. 当前页面截图,跳转页面截图。
    2. 当前页面截图,跳转页面不截图。
    3. 当前页面不截图,跳转页面截图。
    4. 当前页面不截图,跳转页面不截图。

    virtual void TransitionAlg(uint32_t time)

    动效过程中调用,基于时间对初始化的控件进行状态调整。

    virtual void OnTransitionEnd()

    动效结束时调用,根据需要释放动效过程中申请的资源或者状态重置(按需实现)。

  3. 在动效源文件中调用REGIST_TRANSITION将其注册到TransitionManager中。

    REGIST_TRANSITION函数宏原型如下:

    #define REGIST_TRANSITION(type, func, time, enableCurSnapShot, enableTargetSnapShot) \
    
        const static OHOS::TransitionRegister (STATIC_VAR)(type, new func(time, enableCurSnapShot, enableTargetSnapShot))
    

    例如:

    REGIST_TRANSITION(TransitionType::TRANSITION_ZOOM, ZoomTransition, 800, true, true);
    

    表 2 REGIST_TRANSITION注册参数解析

    参数

    说明

    type

    动效ID(在头文件“TransitionType.h”中管理)。

    func

    动效类名作为入参。

    time

    动画特效所需的时间,单位:ms。

    enableCurSnapShot

    是否使能当前Slice的截图。

    enableTargetSnapShot

    是否使能目标Slice的截图。

不同配置的动效对Slice生命周期的影响

首先,无论跳转是否有动效,Slice里面各个生命周期的期望行为是保持不变;其次,基于是否使用截图,当前动画一共分为四类,不同的动画,生命周期调用会有些许差异:

  • Slice A使用截图、Slice B使用截图

    Slice A OnPause -> Slice A OnStop -> Slice B OnStart -> Animator -> Slice B OnResume

  • Slice A使用截图、Slice B不使用截图

    Slice A OnPause -> Slice A OnStop -> Slice B OnStart -> Animator -> Slice B OnResume

  • Slice A不使用截图、Slice B使用截图

    Slice A OnPause -> Slice B OnStart -> Animator -> Slice A OnStop -> Slice B OnResume

  • Slice A不使用截图、Slice B不使用截图

    Slice A OnPause -> Slice B OnStart -> Animator -> Slice A OnStop -> Slice B OnResume

更多细节可参考 TransitionCallback.h 中的注释。

支持Slice跟手返回

Slice跟手返回,是指当从Slice A切换到Slice B后,Slice B界面可以跟手左右滑动。如果滑动松手时的距离超过屏幕的一半,那么Slice B会逐渐退出屏幕,并最终只显示Slice A的界面。具体效果可参考图1

图 1 Slice跟手返回效果示例

Slice跟手返回效果示例

Slice跟手返回需要将Slice跳转方法中的参数enableSlideBack设置为true。

为了支持Slice跟手返回,系统会自动在跳转过程中对即将销毁的Slice进行截图。另外,也提供对外接口SaveSlideBackSnapShotIfNecessary供开发者定制截图内容。比如在一级页面下拉菜单中跳转到设置页面后,需要跟手返回到一级页面的表盘界面,此时就需要定制,具体可参考用例MainPresenterSample:

void MainPresenterSample::OnPause()

{

    Presenter<MainViewSample>::OnPause();

    // Save watchface content for slide back

    UIView* watchFace = view_->GetViewById(WATCH_FACE)->GetParent();

    uint8_t opaScale = watchFace->GetOpaScale();

    watchFace->SetOpaScale(OPA_OPAQUE);

    PageTransitionMgr::GetInstance().SaveSlideBackSnapShotIfNecessary(watchFace);

    watchFace->SetOpaScale(opaScale);

    mainPresenterState_ = MainPresenterState::PAUSE;

}

说明:

  1. 以下情况会导致历史截图被删除,进而不能够跟手返回:

  2. 没有连续设置跟手返回,例如从A进入B设置跟手返回、B进入C不设置跟手返回,那么A的截图将会被删除。

  3. 跟手返回最多只支持3张截图,例如从A进入B,B进入C,C进入D都设置了跟手返回,当前在D能够跟手返回到C。但如果从D进入到E,将会删除历史截图,在E界面不能跟手返回,只能通过其他方式跳转。

  4. 只能跟手返回到Native应用。

  5. 由于当前Slice的根容器控件通过监听拖拽事件进行跟手返回,当子控件同时监听拖拽事件的时候就会存在滑动冲突的问题,具体场景和对应方案如下:

  6. 子控件内容支持水平方向或竖直方向滑动(如UIList、UISwipeView及UIScrollView),建议客户根据需要使用UIListNested、UISwipeViewNested和UIScrollViewNested替代相应的类,具体参考Demo代码SettingView.cpp、SetDesktopView.cpp。

  7. 客户Slice内部嵌套多级页面,支持右滑返回上一级。如果多级子页面监听根容器的右滑事件,会与Slice跟手返回冲突。建议客户将Slice中多级页面的右滑监听配到到内部子页面,并拦截事件分发。

SlicePage跳转

SlicePage跳转方法说明

SlicePage跳转是指Slice内部SlicePage间的跳转,可以使用如下两种跳转方式:

  • 使用NativeAbility提供的SwitchSliceInPage方法跳转到另一个SlicePage。

      bool SwitchSliceInPage(uint16_t pageId, void* data = nullptr,
    
          TransitionType type =  TransitionType::TRANSITION_INVALID, bool canBack = false);
    

    表 1 NativeAbility::SwitchSliceInPage参数说明

    参数

    说明

    pageId

    目标SlicePage的ID。

    data

    用于SlicePage间的数据传递,传递过程中不会做data备份。

    type

    跳转动效类型,默认为TransitionType::TRANSITION_INVALID,即无动效。动效可复用不使用截图的TransitionCallback实例。

    canBack

    是否缓存当前页面,并支持跟手返回,默认值为false。

    如果Slice正在切换或者Slice内部的SlicePage正在切换,则该操作会被取消,并返回false。

    如果不缓存页面,请不要在该函数调用后继续访问当前slice的成员变量,因为当前slice会在该函数中销毁。

  • 使用NativeAbility提供的BackToPrevSlicePage方法返回到上一个缓存的SlicePage:

      bool BackToPrevSlicePage();
    

    如果Slice正在切换、Slice内部的SlicePage正在切换或者没有缓存的Slice Page,则该操作会被取消,并返回false。

    请不要在该函数调用后继续访问当前slice的成员变量,因为当前slice会在该函数中销毁。

支持SlicePage跳转动效

SlicePage的跳转动效可复用不使用截图的Slice跳转动效,即参数enableCurrentSnapShot和enableTargetSnapShot均为false的TransitionCallback实现类。开发者可以参考“支持Slice跳转动效”章节定制SlicePage跳转动效。

在有跳转动效的场景,为了保证跳转过程中当前页面还能够实时变化,Slice内部SlicePage跳转的生命周期会有差异。以SlicePage A跳转到SlicePage B为例,生命周期如下:

SlicePage B OnStart -> Animator -> SlicePage A OnPause -> SlicePage A OnStop -> SlicePage B OnResume

支持SlicePage跟手返回

SlicePage可以在跳转的时候指定是否缓存,如果缓存(参数canBack为true),那么在跳转离开后仍能够跟手返回到当前SlicePage。

SlicePage跟手返回需要注意如下约束:

  • 未限制可缓存的SlicePage的数量,因此开发者在使用该功能的时候需考虑整个系统内存的限制。

  • 如果Slice内部SlicePage的跳转不需要缓存,则会清空当前Slice内部已缓存的SlicePage。

  • 如果跳转离开当前Slice,当前Slice内部的SlicePage缓存也会被清空。

  • 如果SlicePage既要跟手返回到前一个页面,又要支持内部滑动,需要参考“支持Slice跟手返回”章节妥善处理嵌套滑动问题。