【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现
📚 目录
[【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现](#【开源鸿蒙跨平台开发先锋训练营】DAY8~DAY13 底部选项卡&我的页面功能实现)
[📝 摘 要](#📝 摘 要)
[🔍 1 概述](#🔍 1 概述)
[1.1 开发背景](#1.1 开发背景)
[1.2 开发目标](#1.2 开发目标)
[1.3 核心技术栈](#1.3 核心技术栈)
[🛠️ 2 开发环境准备](#🛠️ 2 开发环境准备)
[2.1 环境配置](#2.1 环境配置)
[2.2 本地资源配置](#2.2 本地资源配置)
[2.3 我的页面目录结构](#2.3 我的页面目录结构)
[🧩 3 我的页面功能实现](#🧩 3 我的页面功能实现)
[3.1 主页面入口实现](#3.1 主页面入口实现)
[3.2 核心组件实现](#3.2 核心组件实现)
[3.3 子页面实现](#3.3 子页面实现)
[📱 4 运行验证与效果展示](#📱 4 运行验证与效果展示)
[4.1 我的主页面](#4.1 我的主页面)
[4.2 子页面效果](#4.2 子页面效果)
[🎯 5 总结与拓展](#🎯 5 总结与拓展)
[5.1 总结](#5.1 总结)
[5.2 拓展方向](#5.2 拓展方向)
[📚 6 参考资料](#📚 6 参考资料)
📝 摘 要
本文记录开源鸿蒙跨平台开发先锋训练营 DAY8~DAY13 的实践成果,聚焦底部选项卡适配与我的页面模块化落地。开发中严格遵循项目 "页面级模块化" 规范,搭建了 pages/mine/ 专属目录,内含 components/、models/ 子目录及完整子页面文件,实现组件与业务逻辑的解耦;完成底部选项卡与多页面的联动适配,以及我的页面从用户信息展示到收藏、设置等子页面的全功能静态路由实现,代码结构清晰,符合鸿蒙跨平台开发规范。
🔍 1 概述
1.1 开发背景
在基于 Flutter 的跨端美食类应用开发中,我的页面是承载用户个人数据、系统设置的核心模块。为了保持项目的模块化与可维护性,我延续了应用中其他页面(如首页、美食、动态)的开发规范,对我的页面进行了组件化拆分与功能实现。
1.2 开发目标
📌 完成我的页面从 0 到 1 的模块化搭建,包含用户信息展示、我的收藏、浏览历史、我的发布、设置、帮助与反馈等核心功能。
📌 解决网络图片加载失败、未使用导入警告等开发问题,提升界面稳定性与代码整洁度。
📌 保持与现有项目目录结构的一致性,遵循 "页面级模块化" 设计原则。
1.3 核心技术栈
⚡ 跨平台框架:Flutter(兼容OpenHarmony)
💻 开发工具:VS Code(代码编写)、DevEco Studio 6.0.0 Release(鸿蒙设备调试)
📊 资源管理:pubspec.yaml 本地资源配置
🛠️ 2 开发环境准备
2.1 环境配置
🚀 Flutter环境:安装 Flutter 3.27.5版本,配置flutter-OHOS-1.0.1(鸿蒙适配分支)分支(兼容 OpenHarmony);
📱 鸿蒙环境:安装DevEco Studio 6.0.0 Release,配置 OpenHarmony SDK(API Version 20(6.0.0.47)),创建鸿蒙模拟器;
📂 项目初始化:基于现有flutter_harmonyos工程,调整目录结构,安装依赖。
2.2 本地资源配置
在 pubspec.yaml 中声明推荐页面图片资源路径,确保图片正常加载:
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/images/foods/ # 美食卡片图片
- assets/images/food_show/ # 美食页相关图片
- assets/images/food_show/dynamic/ # 清单页动态图
- assets/images/food_show/star/ # 排行页达人头像
- assets/images/food_show/task/ # 任务中心图标
- assets/images/food_note/ # 动态模块根资源
- assets/images/food_note/avatar/ # 用户头像资源
- assets/images/food_note/dynamic/ # 动态图片资源
- assets/images/eat_what/ # 推荐页面资源
- assets/images/mine/ # 我的页面资源
2.3 我的页面目录结构
遵循项目现有 "页面级模块化" 规范,每个模块独立维护 components、models、子页面等文件,目录结构如下:
lib/
└─ pages/
└─ mine/
├─ components/ # 页面子组件
│ ├─ user_info_widget.dart # 用户信息卡片组件
│ ├─ mine_function_item.dart # 功能列表条目组件
│ └─ mine_section_widget.dart # 功能分组标题组件
├─ models/ # 页面专属模型
│ ├─ user_model.dart # 用户信息模型
│ └─ mine_function_model.dart # 功能条目模型
├─ mine_page.dart # 主页面入口
├─ my_collection_page.dart # 我的收藏页面
├─ my_history_page.dart # 我的浏览历史页面
├─ my_publish_page.dart # 我的发布页面
├─ settings_page.dart # 设置页面
└─ feedback_page.dart # 帮助与反馈页面
🧩 3 我的页面功能实现
3.1 主页面入口实现
mine_page.dart 作为"我的"页面的主入口,负责整合所有子组件与功能条目:
✅ 用户信息区:通过 UserInfoWidget 展示昵称、个性签名。
✅ 功能分组:通过 MineSectionWidget 划分 "我的内容" 与 "系统设置" 模块。
✅ 功能条目:通过 MineFunctionItem 统一实现可点击的功能入口。
// mine/ # 我的页面
// lib/pages/mine/mine_page.dart(我的)
import 'package:flutter/material.dart';
import 'components/user_info_widget.dart';
import 'components/mine_section_widget.dart';
import 'components/mine_function_item.dart';
// 导入子页面
import 'my_collection_page.dart';
import 'my_history_page.dart';
import 'settings_page.dart';
import 'feedback_page.dart';
import 'my_publish_page.dart';
class MinePage extends StatelessWidget {
const MinePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
// 用户信息区
const UserInfoWidget(
userName: '美食爱好者',
signature: '分享美食,记录生活',
),
// 我的内容分组
const MineSectionWidget(title: '我的内容'),
MineFunctionItem(
icon: Icons.bookmark_border,
title: '我的收藏',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const MyCollectionPage()),
),
),
MineFunctionItem(
icon: Icons.history,
title: '浏览历史',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const MyHistoryPage()),
),
),
// 我的发布功能条目
MineFunctionItem(
icon: Icons.edit_note, // 匹配发布的图标
title: '我的发布',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const MyPublishPage()),
),
),
// 系统设置分组
const MineSectionWidget(title: '系统设置'),
MineFunctionItem(
icon: Icons.settings,
title: '设置',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsPage()),
),
),
MineFunctionItem(
icon: Icons.help_outline,
title: '帮助与反馈',
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const FeedbackPage()),
),
),
],
),
);
}
}
3.2 核心组件实现
user_info_widget.dart:用户信息卡片组件。
UserInfoWidget(用户信息卡片):
"我的" 页面顶部核心组件,展示用户头像(支持网络头像 / 本地默认占位图,加载失败自动兜底)、昵称、个性签名;内置头像右下角编辑入口,支持扩展积分 / 等级等额外信息,样式统一且可灵活定制。
// user_info_widget.dart # 用户信息卡片组件
import 'package:flutter/material.dart';
// 我的页面用户信息卡片组件
// 包含:头像、昵称、个性签名、编辑入口,支持扩展积分/等级等信息
class UserInfoWidget extends StatelessWidget {
final String userName; // 用户名(默认显示"美食爱好者")
final String? signature; // 个性签名(可选,默认显示"分享美食,记录生活")
final String? avatarUrl; // 用户头像URL(默认显示本地占位图)
final VoidCallback? onEditTap; // 编辑信息点击回调
final String? extraInfo; // 积分/等级提示(可选,如"积分: 128")
const UserInfoWidget({
super.key,
this.userName = "美食爱好者",
this.signature = "分享美食,记录生活",
this.avatarUrl,
this.onEditTap,
this.extraInfo,
});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 1. 用户头像
Stack(
children: [
ClipOval(
child: avatarUrl != null
? // 网络头像
Image.network(
avatarUrl!,
width: 70,
height: 70,
fit: BoxFit.cover,
// 加载失败时显示默认头像
errorBuilder: (context, error, stackTrace) => _defaultAvatar(),
)
: // 默认本地头像
_defaultAvatar(),
),
// 头像右下角编辑小图标
Positioned(
bottom: 0,
right: 0,
child: GestureDetector(
onTap: onEditTap,
child: Container(
width: 24,
height: 24,
decoration: BoxDecoration(
color: const Color(0xFFFC6940),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.white, width: 2),
),
child: const Icon(
Icons.edit,
size: 14,
color: Colors.white,
),
),
),
),
],
),
const SizedBox(width: 16),
// 2. 用户信息(昵称、签名、额外信息)
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
userName,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Color(0xFF333333),
),
),
if (signature != null)
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
signature!,
style: TextStyle(
fontSize: 14,
color: const Color(0xFF999999),
// 签名过长时省略
overflow: TextOverflow.ellipsis,
),
),
),
if (extraInfo != null)
Padding(
padding: const EdgeInsets.only(top: 6),
child: Text(
extraInfo!,
style: const TextStyle(
fontSize: 12,
color: Color(0xFFFC6940),
),
),
),
],
),
),
],
),
);
}
/// 默认占位头像(本地资源,在pubspec.yaml中配置assets)
Widget _defaultAvatar() {
return Image.asset(
'assets/images/mine/avatar_default.png', // 本地头像路径
width: 70,
height: 70,
fit: BoxFit.cover,
);
}
}
mine_function_item.dart:功能列表条目组件。
MineFunctionItem(功能条目组件):
统一功能条目的样式(图标 + 标题 + 右侧默认箭头 / 自定义提示组件),内置 Material Design 点击水波纹交互;支持点击回调、自定义图标 / 标题颜色、可选底部分割线,适配"我的"页面及应用内所有功能入口场景。
// mine_function_item.dart # 功能列表条目组件
import 'package:flutter/material.dart';
// 我的页面统一功能条目组件
// 支持:图标、标题、右侧箭头、点击回调、自定义右侧提示
class MineFunctionItem extends StatelessWidget {
final IconData icon; // 左侧功能图标
final String title; // 功能标题文字
final VoidCallback? onTap; // 点击回调事件
final Widget? rightWidget; // 右侧自定义提示(如数字、"NEW"标签,默认显示箭头)
final Color iconColor; // 图标颜色(默认主题色,可自定义)
final Color titleColor; // 标题文字颜色(默认黑色,可自定义)
final bool showDivider; // 是否显示底部分割线(默认显示)
const MineFunctionItem({
super.key,
required this.icon,
required this.title,
this.onTap,
this.rightWidget,
this.iconColor = const Color(0xFFFC6940), // 适配美食APP的暖色调主题
this.titleColor = const Color(0xFF333333),
this.showDivider = true,
});
@override
Widget build(BuildContext context) {
return InkWell(
// 点击水波纹效果,符合Material Design规范
onTap: onTap,
borderRadius: BorderRadius.circular(0),
child: Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 左侧图标
Icon(
icon,
size: 22,
color: iconColor,
),
const SizedBox(width: 12), // 图标与标题间距
// 功能标题
Expanded(
child: Text(
title,
style: TextStyle(
fontSize: 16,
color: titleColor,
),
),
),
// 右侧组件(默认箭头,可自定义)
rightWidget ??
const Icon(
Icons.arrow_forward_ios,
size: 16,
color: Color(0xFFCCCCCC),
),
],
),
// 底部分割线(可选)
if (showDivider)
const Padding(
padding: EdgeInsets.only(left: 48, top: 14), // 对齐标题位置
child: Divider(
height: 1,
color: Color(0xFFF5F5F5),
),
),
],
),
),
);
}
}
mine_section_widget.dart:功能分组标题组件。
MineSectionWidget(功能分组标题):
用于"我的"页面划分功能模块(如"我的内容"、"系统设置")的分组标题;支持自定义标题文字、左侧间距(适配不同布局)、文字颜色,内置固定的上下间距(上12dp / 下8dp),统一分组标题的视觉样式。
// mine_section_widget.dart# 功能分组标题组件
import 'package:flutter/material.dart';
// 我的页面功能分组标题组件
// 示例:"我的内容"、"系统设置" 等分组标题
class MineSectionWidget extends StatelessWidget {
final String title; // 分组标题文字
final double paddingLeft; // 标题左侧间距(默认16dp,适配不同布局)
final Color textColor; // 标题文字颜色(默认灰色,可自定义)
const MineSectionWidget({
super.key,
required this.title,
this.paddingLeft = 16.0,
this.textColor = const Color(0xFF666666),
});
@override
Widget build(BuildContext context) {
return Padding(
// 上下间距12dp,左侧自定义间距,右侧16dp
padding: EdgeInsets.fromLTRB(paddingLeft, 12, 16, 8),
child: Text(
title,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: textColor,
),
),
);
}
}
3.3 子页面实现
my_collection_page.dart(我的收藏):使用 ListView.builder 展示收藏列表。
// my_collection_page.dart # 我的收藏页面
import 'package:flutter/material.dart';
class MyCollectionPage extends StatelessWidget {
const MyCollectionPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('我的收藏'),
centerTitle: true,
),
body: ListView.builder(
itemCount: 10, // 模拟数据
itemBuilder: (context, index) {
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
// 替换为本地图片加载(删除Image.network,改用Image.asset)
child: Image.asset(
'assets/images/mine/default-food.png', // 本地图片路径
width: 60,
height: 60,
fit: BoxFit.cover,
// 本地图加载失败的保险处理(路径正确则不会触发)
errorBuilder: (context, error, stackTrace) {
return Container(
width: 60,
height: 60,
color: Colors.grey[200],
child: const Icon(Icons.image, color: Colors.grey, size: 24),
);
},
),
),
title: Text('收藏过的美食 $index'),
subtitle: const Text('收藏于 2026-02-01'),
onTap: () {
// 跳转美食详情
},
);
},
),
);
}
}
my_history_page.dart(浏览历史):
// my_history_page.dart # 我的浏览历史页面
import 'package:flutter/material.dart';
class MyHistoryPage extends StatelessWidget {
const MyHistoryPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('浏览历史'),
centerTitle: true,
actions: [
TextButton(
onPressed: () {
// 清空历史逻辑
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('浏览历史已清空')),
);
},
child: const Text(
'清空',
style: TextStyle(color: Color(0xFFFC6940)),
),
),
],
),
body: ListView.builder(
itemCount: 8, // 模拟数据
itemBuilder: (context, index) {
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(8),
// 替换为本地图片加载(删除Image.network,改用Image.asset)
child: Image.asset(
'assets/images/mine/default-food.png', // 本地图片路径
width: 60,
height: 60,
fit: BoxFit.cover,
// 本地图加载失败的保险处理(路径正确则不会触发)
errorBuilder: (context, error, stackTrace) {
return Container(
width: 60,
height: 60,
color: Colors.grey[200],
child: const Icon(Icons.image, color: Colors.grey, size: 24),
);
},
),
),
title: Text('浏览过的美食 $index'),
subtitle: const Text('浏览于 2026-02-01'),
onTap: () {
// 跳转美食详情
},
);
},
),
);
}
}
my_publish_page.dart(我的发布):
// my_publish_page.dart # 我的发布页面
import 'package:flutter/material.dart';
class MyPublishPage extends StatelessWidget {
const MyPublishPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('我的发布'),
centerTitle: true,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(
Icons.article_outlined,
size: 80,
color: Color(0xFFCCCCCC),
),
const SizedBox(height: 16),
const Text(
'您还没有发布过内容',
style: TextStyle(
fontSize: 16,
color: Color(0xFF999999),
),
),
const SizedBox(height: 24),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFFC6940), // 匹配APP主题色
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
onPressed: () {
// 这里可以跳转"发布美食"的页面(后续可补充路由)
},
child: const Text(
'去发布',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
],
),
),
);
}
}
settings_page.dart(设置):
// settings_page.dart # 设置页面
import 'package:flutter/material.dart';
class SettingsPage extends StatefulWidget {
const SettingsPage({super.key});
@override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
// 主题颜色选择
List<Color> themeColors = [
const Color(0xFFFF5722),
const Color(0xFF4CAF50),
const Color(0xFF2196F3),
const Color(0xFF9C27B0),
const Color(0xFFFFC107),
Colors.black,
];
int selectedColorIndex = 4; // 默认选中橙色
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('设置'),
centerTitle: true,
),
body: ListView(
children: [
// 主题切换
const ListTile(
title: Text('主题'),
leading: Icon(Icons.color_lens, color: Color(0xFFFC6940)),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Wrap(
spacing: 12,
children: List.generate(themeColors.length, (index) {
return GestureDetector(
onTap: () {
setState(() {
selectedColorIndex = index;
});
},
child: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: themeColors[index],
borderRadius: BorderRadius.circular(20),
border: selectedColorIndex == index
? Border.all(color: Colors.white, width: 3)
: null,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
),
],
),
),
);
}),
),
),
const Divider(height: 1),
// 多语言
ListTile(
title: const Text('多语言'),
leading: const Icon(Icons.language, color: Color(0xFFFC6940)),
trailing: const Text('跟随系统'),
onTap: () {
// 多语言选择逻辑
},
),
const Divider(height: 1),
// 清除缓存
ListTile(
title: const Text('清除缓存'),
leading: const Icon(Icons.delete_sweep, color: Color(0xFFFC6940)),
trailing: const Text('32.66M'),
onTap: () {
// 清除缓存逻辑
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('缓存已清除')),
);
},
),
const Divider(height: 1),
// 关于我们
ListTile(
title: const Text('关于我们'),
leading: const Icon(Icons.info_outline, color: Color(0xFFFC6940)),
onTap: () {
// 跳转关于页面
},
),
],
),
);
}
}
feedback_page.dart(帮助与反馈):
// feedback_page.dart # 帮助与反馈页面
import 'package:flutter/material.dart';
class FeedbackPage extends StatefulWidget {
const FeedbackPage({super.key});
@override
State<FeedbackPage> createState() => _FeedbackPageState();
}
class _FeedbackPageState extends State<FeedbackPage> {
final TextEditingController _feedbackController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('帮助与反馈'),
centerTitle: true,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Expanded(
child: TextField(
controller: _feedbackController,
maxLines: null,
expands: true,
textAlignVertical: TextAlignVertical.top,
decoration: const InputDecoration(
hintText: '请描述您的问题或建议...',
border: OutlineInputBorder(),
contentPadding: EdgeInsets.all(12),
),
),
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFFC6940),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
),
onPressed: () {
// 提交反馈逻辑
if (_feedbackController.text.isNotEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('反馈提交成功,感谢您的建议!')),
);
Navigator.pop(context);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('请输入您的反馈内容')),
);
}
},
child: const Text('提交'),
),
),
],
),
),
);
}
}
📱 4 运行验证与效果展示
4.1 我的主页面
展示用户信息与所有功能入口,点击条目可直接跳转至对应子页面,界面风格统一,交互流畅。

4.2 子页面效果
我的收藏页面,静态列表展示,图片加载稳定;

浏览历史,设计支持清空功能(暂时不能使用),交互反馈及时;

我的发布,空状态引导清晰,按钮交互友好;

设置,计划设计主题切换、缓存清除功能;

帮助与反馈,文本输入与提交功能正常。


🎯 5 总结与拓展
5.1 总结
本次实现遵循了项目现有的模块化设计规范,通过组件化拆分,完成了我的页面的基础功能开发。包括:
✅ 模块化结构:每个页面独立维护组件与模型,代码职责清晰,可维护性高。
✅ 容错处理:网络图片加载失败时自动切换本地占位图,提升界面稳定性。
✅ 代码整洁:通过删除未使用导入、局部 const 优化,消除所有 IDE 警告。
5.2 拓展方向
完善已有页面布局,为开源鸿蒙跨平台应用全面集成动效能力,覆盖页面转场、组件交互、数据加载等核心场景,提升应用视觉体验与交互流畅度,并完成开源鸿蒙设备运行验证。
📚 6 参考资料
🔗 参考前文:
https://blog.csdn.net/m0_74451345/article/details/156915775?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157024056?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157032531?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157094159?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157464927?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157505773?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157542849?spm=1001.2014.3001.5502
https://blog.csdn.net/m0_74451345/article/details/157583805?spm=1001.2014.3001.5501
🔗 参考三方库:
OpenHarmony兼容的三方库:https://gitcode.com/openharmony-tpc/flutter_packages
🔗文章中AtomGit开源项目个人仓库链接:
https://atomgit.com/zhangxupeng2025/flutter_HmProject
ℹ️ 博客说明:本文为训练营实战记录,代码可在我的AtomGit个人公开仓库克隆到本地配置后直接运行(部分资源需要本地配置,比如需替换本地图片资源),后续将完善已有页面布局,为开源鸿蒙跨平台应用全面集成动效能力,覆盖页面转场、组件交互、数据加载等核心场景,提升应用视觉体验与交互流畅度,文中也有许多待优化点,欢迎大家关注交流~
最后,
欢迎加入开源鸿蒙跨平台社区: