news 2026/7/11 13:52:58

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HarmonyOS《柚兔学伴》项目实战06-闪屏页与动画

06 闪屏页与动画

闪屏页(Splash Screen)是应用启动后的第一个页面,承担着品牌展示、资源预加载和页面跳转的职责。本文将围绕「柚兔学伴」项目的SplashPage.etsSplashViewModel.ets,讲解如何利用 ArkUI 的页面生命周期、animateTo全局动画 API 以及事件驱动的 ViewModel 架构来构建一个完整的闪屏页。


1. SplashPage 整体结构

SplashPage使用@Entry+@Component装饰器声明为页面入口组件:

import{ConfigurationConstant}from'@kit.AbilityKit';import{CommonConstants,Logger,PageContext,WindowUtil}from'common';import{SplashEventTypeEnum,SplashViewModel}from'../viewmodel/SplashViewModel';@Entry@Componentstruct SplashPage{privatepageContext:PageContext=AppStorage.get('pageContext')asPageContext;privateappPathInfo:NavPathStack=this.pageContext.navPathStack;privateviewModel:SplashViewModel=newSplashViewModel();// ...}

关键点:

  • @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 执行时序

页面加载后,按照以下时序依次执行:

  1. 更新状态栏颜色——WindowUtil.updateStatusBarColor传入true表示使用浅色状态栏(白底黑字),以匹配闪屏背景。
  2. 检查首次启动——发送CHECK_FIRST_START事件,ViewModel 判断是否首次打开应用并记录标记。
  3. 启动动画——调用animateTo,在动画闭包中发送PRELOAD_RESOURCES事件预加载资源。
  4. 动画结束跳转——onFinish回调中发送JUMP_TO_MAIN事件,导航到主页。

2.2 animateTo 全局动画 API

animateTo是 ArkUI 提供的全局隐式动画接口,签名如下:

animateTo(value:AnimateParam,task:()=>void):void
参数说明
value动画参数对象,包含durationdelaycurveonFinish
task动画闭包,闭包内触发的属性变化会自动以动画形式过渡

在本项目中:

  • delay: CommonConstants.ANIMATION_DELAY(500ms)——延迟启动,确保页面渲染完毕。
  • duration: CommonConstants.ANIMATION_DURATION(1000ms)——动画持续时长。
  • onFinish——动画完成后的回调,用于触发页面跳转。

注意animateTo内的闭包应当只包含 UI 属性修改。如果只需延时执行逻辑而不涉及 UI 属性动画,也可以考虑使用setTimeout替代。本项目中闭包内调用PRELOAD_RESOURCES事件,是在动画期间并行执行预加载任务。


3. 事件驱动的 ViewModel

SplashViewModel继承自BaseVM<BaseState>,采用事件驱动架构:

3.1 BaseVM 抽象基类

// common/src/main/ets/viewmodel/BaseVM.etsexportabstractclassBaseVM<TextendsBaseState>{protectedstate:T;publicconstructor(initialState:T){this.state=initialState;}getState():T{returnthis.state;}publicabstractsendEvent(baseVMEvent:BaseVMEvent);}

设计要点:

  • 泛型T extends BaseState:每个 ViewModel 可以定义自己的状态类型。
  • sendEvent抽象方法:子类必须实现,通过事件类型分发到不同的处理方法。
  • getState:暴露当前状态给 UI 层读取。

3.2 SplashViewModel 实现

exportclassSplashViewModelextendsBaseVM<BaseState>{privatepageContext:PageContext=AppStorage.get('pageContext')asPageContext;privatepreferenceManager:PreferenceManager=PreferenceManager.getInstance();publicconstructor(){super(newBaseState());}publicsendEvent(eventType:SplashEventTypeEnum):void{if(eventType===SplashEventTypeEnum.JUMP_TO_MAIN){this.jumpToMainPage();}elseif(eventType===SplashEventTypeEnum.PRELOAD_RESOURCES){this.preloadResources();}elseif(eventType===SplashEventTypeEnum.CHECK_FIRST_START){this.checkIsFirstStart();}}}

3.3 事件枚举

exportenumSplashEventTypeEnum{JUMP_TO_MAIN='jumpToMainPage',PRELOAD_RESOURCES='preloadResources',CHECK_FIRST_START='checkIsFirstStart',}

使用枚举而非硬编码字符串,确保事件名的类型安全和可维护性。

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. 总结

知识点说明
@Entry+@Component页面入口组件声明
aboutToAppear页面出现前回调,适合初始化逻辑
animateTo全局隐式动画 API,支持 delay/duration/onFinish
BaseVM<T>抽象 ViewModel 基类,事件驱动架构
sendEvent+ 枚举类型安全的事件分发机制
Navigation+NavPathStack声明式导航与路由栈管理
$r()资源引用语法,访问 media/string/color 资源
onPageHide页面隐藏回调,用于资源清理或状态恢复
PreferenceManager轻量级键值对持久化存储

闪屏页看似简单,却串联了 ArkUI 的页面生命周期、动画系统、导航框架和 ViewModel 架构等多个核心概念。掌握这些模式,将为后续复杂页面的开发打下坚实基础。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 13:51:21

2026年AI生成网页HTML,可导出源码建站工具盘点

2026年AI生成网页HTML&#xff0c;可导出源码建站工具盘点一、源码导出需求为什么越来越强2026年&#xff0c;企业对网站数据自主权的意识明显增强。据艾瑞咨询联合IDC发布的行业数据显示&#xff0c;国内网站建设行业市场规模已突破980亿元。超过55%的企业因选型失误导致项目返…

作者头像 李华
网站建设 2026/7/11 13:50:16

C++ 块作用域详解:从基础到实战

1. 什么是块作用域在 C 中&#xff0c;块作用域&#xff08;Block Scope&#xff09;指的是由一对花括号 {} 所限定的代码区域。在这个区域内声明的变量、常量或对象&#xff0c;其生命周期和可见性都仅限于该块内部。块作用域是 C 最基本的作用域类型之一&#xff0c;理解它对…

作者头像 李华
网站建设 2026/7/11 13:46:30

如何轻松保存抖音内容:完整免费下载方案终极指南

如何轻松保存抖音内容&#xff1a;完整免费下载方案终极指南 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖…

作者头像 李华
网站建设 2026/7/11 13:42:45

如何免费获取8大网盘直链下载地址:终极完整指南

如何免费获取8大网盘直链下载地址&#xff1a;终极完整指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 /…

作者头像 李华