HarmonyOS《柚兔学伴》项目实战06-闪屏页与动画

发布时间:2026/7/11 13:53:07
HarmonyOS《柚兔学伴》项目实战06-闪屏页与动画 06 闪屏页与动画闪屏页Splash Screen是应用启动后的第一个页面承担着品牌展示、资源预加载和页面跳转的职责。本文将围绕「柚兔学伴」项目的SplashPage.ets和SplashViewModel.ets讲解如何利用 ArkUI 的页面生命周期、animateTo全局动画 API 以及事件驱动的 ViewModel 架构来构建一个完整的闪屏页。1. SplashPage 整体结构SplashPage使用EntryComponent装饰器声明为页面入口组件import{ConfigurationConstant}fromkit.AbilityKit;import{CommonConstants,Logger,PageContext,WindowUtil}fromcommon;import{SplashEventTypeEnum,SplashViewModel}from../viewmodel/SplashViewModel;EntryComponentstruct SplashPage{privatepageContext:PageContextAppStorage.get(pageContext)asPageContext;privateappPathInfo:NavPathStackthis.pageContext.navPathStack;privateviewModel:SplashViewModelnewSplashViewModel();// ...}关键点Entry将该组件标记为页面路由入口框架会自动注册路由表。PageContext从AppStorage获取全局页面上下文其中包含NavPathStack导航栈用于页面跳转。SplashViewModel事件驱动的 ViewModel 实例负责处理业务逻辑。2. 页面生命周期与动画流程闪屏页的核心逻辑集中在aboutToAppear生命周期回调中aboutToAppear():void{WindowUtil.updateStatusBarColor(getContext(this),true);this.viewModel.sendEvent(SplashEventTypeEnum.CHECK_FIRST_START);animateTo({delay:CommonConstants.ANIMATION_DELAY,duration:CommonConstants.ANIMATION_DURATION,onFinish:(){this.viewModel.sendEvent(SplashEventTypeEnum.JUMP_TO_MAIN);}},(){this.viewModel.sendEvent(SplashEventTypeEnum.PRELOAD_RESOURCES);})}2.1 执行时序页面加载后按照以下时序依次执行更新状态栏颜色——WindowUtil.updateStatusBarColor传入true表示使用浅色状态栏白底黑字以匹配闪屏背景。检查首次启动——发送CHECK_FIRST_START事件ViewModel 判断是否首次打开应用并记录标记。启动动画——调用animateTo在动画闭包中发送PRELOAD_RESOURCES事件预加载资源。动画结束跳转——onFinish回调中发送JUMP_TO_MAIN事件导航到主页。2.2 animateTo 全局动画 APIanimateTo是 ArkUI 提供的全局隐式动画接口签名如下animateTo(value:AnimateParam,task:()void):void参数说明value动画参数对象包含duration、delay、curve、onFinish等task动画闭包闭包内触发的属性变化会自动以动画形式过渡在本项目中delay: CommonConstants.ANIMATION_DELAY500ms——延迟启动确保页面渲染完毕。duration: CommonConstants.ANIMATION_DURATION1000ms——动画持续时长。onFinish——动画完成后的回调用于触发页面跳转。注意animateTo内的闭包应当只包含 UI 属性修改。如果只需延时执行逻辑而不涉及 UI 属性动画也可以考虑使用setTimeout替代。本项目中闭包内调用PRELOAD_RESOURCES事件是在动画期间并行执行预加载任务。3. 事件驱动的 ViewModelSplashViewModel继承自BaseVMBaseState采用事件驱动架构3.1 BaseVM 抽象基类// common/src/main/ets/viewmodel/BaseVM.etsexportabstractclassBaseVMTextendsBaseState{protectedstate:T;publicconstructor(initialState:T){this.stateinitialState;}getState():T{returnthis.state;}publicabstractsendEvent(baseVMEvent:BaseVMEvent);}设计要点泛型T extends BaseState每个 ViewModel 可以定义自己的状态类型。sendEvent抽象方法子类必须实现通过事件类型分发到不同的处理方法。getState暴露当前状态给 UI 层读取。3.2 SplashViewModel 实现exportclassSplashViewModelextendsBaseVMBaseState{privatepageContext:PageContextAppStorage.get(pageContext)asPageContext;privatepreferenceManager:PreferenceManagerPreferenceManager.getInstance();publicconstructor(){super(newBaseState());}publicsendEvent(eventType:SplashEventTypeEnum):void{if(eventTypeSplashEventTypeEnum.JUMP_TO_MAIN){this.jumpToMainPage();}elseif(eventTypeSplashEventTypeEnum.PRELOAD_RESOURCES){this.preloadResources();}elseif(eventTypeSplashEventTypeEnum.CHECK_FIRST_START){this.checkIsFirstStart();}}}3.3 事件枚举exportenumSplashEventTypeEnum{JUMP_TO_MAINjumpToMainPage,PRELOAD_RESOURCESpreloadResources,CHECK_FIRST_STARTcheckIsFirstStart,}使用枚举而非硬编码字符串确保事件名的类型安全和可维护性。3.4 具体事件处理跳转到主页privatejumpToMainPage():void{this.pageContext.replacePage({routerName:MainPage,});}使用replacePage而非pushPage意味着闪屏页会从导航栈中移除用户无法返回闪屏页。检查首次启动privatecheckIsFirstStart():void{this.preferenceManager.hasValue(isFirstStart).then((hasResult:boolean){if(hasResult){Logger.info(TAG,Not first startup.);}else{Logger.info(TAG,First startup.);this.preferenceManager.setValue(isFirstStart,false).then((){Logger.info(TAG,Put the value of startup Successfully.);}).catch((err:BusinessError){Logger.error(TAG,Put the value of startup Failed, err code:${err.code});});}});}通过PreferenceManager持久化存储首次启动标记基于ohos.data.preferences实现。4. UI 构建Navigation 与背景图build(){Navigation(this.appPathInfo){Column().width(100%).height(100%).backgroundImage($r(app.media.ic_splash)).backgroundImageSize({width:100%,height:100%})}.hideTitleBar(true).mode(NavigationMode.Stack).height(100%).width(100%)}4.1 Navigation 容器Navigation(this.appPathInfo)绑定NavPathStack导航栈支持页面路由。.hideTitleBar(true)隐藏标题栏闪屏页需要全屏展示。.mode(NavigationMode.Stack)使用栈管理模式支持pushPage/replacePage等路由操作。4.2 背景图$r(app.media.ic_splash)引用resources/base/media/ic_splash资源这是 ArkUI 的资源引用语法$r(app.type.name)。backgroundImageSize设为{ width: 100%, height: 100% }确保图片铺满整个容器。5. onPageHide状态栏颜色恢复当用户离开闪屏页跳转到主页后需要将状态栏颜色恢复为与系统深浅色模式匹配onPageHide(){Logger.info(TAG,onPageHide);WindowUtil.updateStatusBarColor(getContext(this),AppStorage.get(systemColorMode)ConfigurationConstant.ColorMode.COLOR_MODE_DARK);}onPageHide页面隐藏时的生命周期回调。AppStorage.get(systemColorMode)从全局存储读取当前颜色模式。当系统为深色模式时传入true浅色状态栏否则传入false深色状态栏。6. 总结知识点说明EntryComponent页面入口组件声明aboutToAppear页面出现前回调适合初始化逻辑animateTo全局隐式动画 API支持 delay/duration/onFinishBaseVMT抽象 ViewModel 基类事件驱动架构sendEvent 枚举类型安全的事件分发机制NavigationNavPathStack声明式导航与路由栈管理$r()资源引用语法访问 media/string/color 资源onPageHide页面隐藏回调用于资源清理或状态恢复PreferenceManager轻量级键值对持久化存储闪屏页看似简单却串联了 ArkUI 的页面生命周期、动画系统、导航框架和 ViewModel 架构等多个核心概念。掌握这些模式将为后续复杂页面的开发打下坚实基础。