【开源鸿蒙跨平台开发先锋训练营】Flutter框架下鸿蒙应用图标动态化实践指南
·
应用市场大部分热门榜单应用都是在设计视觉上下功夫,这次计划优化下页面中的图标,使用动态图标来提升下美感。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
一、目标与方案
前段时间看到这个 lucide-animated.com,感觉不错,这些把他接入到项目中
- 将项目中的图标全部替换为 Lucide 风格的动态图标,提升视觉与交互体验(参考 )。
- 使用 Flutter 包 not_static_icons(基于 Lucide、无需 Rive/Lottie),在
lib/widgets/app_icons.dart中封装统一入口,各页面通过该入口使用动态图标;包内未提供的少数图标仍使用 Material Icons 兜底。
二、依赖变更
2.1 pubspec.yaml
替换前:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
dio: ^5.4.0
cached_network_image: ^3.3.1
shared_preferences: ^2.2.2
替换后:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
dio: ^5.4.0
cached_network_image: ^3.3.1
shared_preferences: ^2.2.2
# 动态图标(Lucide 风格动画图标),提升视觉交互
not_static_icons: ^0.31.0
2.2 说明
- 原计划使用 flutter_lucide_animated(与 lucide-animated.com 同源),因该包要求 Dart SDK >= 3.10.1,与当前项目 SDK ^3.6.2 不兼容,故改用 not_static_icons。
- not_static_icons 同样基于 Lucide、提供 350+ 动画图标,支持 hover/触摸触发动画、可配置时长与颜色,且仅依赖 Flutter,与当前环境兼容。
三、新增文件:统一图标入口
文件:lib/widgets/app_icons.dart
- 对外提供一组方法:
appArrowBackIcon、appHeartIcon、appBookmarkIcon、appHomeIcon、appSearchIcon、appMessageIcon、appUserIcon、appChevronRightIcon、appSettingsIcon、appHistoryIcon、appLogOutIcon、appRefreshIcon、appUserPlusIcon、appSendIcon、appImageOffIcon、appCircleAlertIcon、appGridIcon、appListIcon等。 - 每个方法支持
size、color、interactive、部分支持controller;默认动画时长 400ms。 - 设置、添加用户 等包内无合适图标时使用 Material Icons(如
Icons.settings_outlined、Icons.person_add_alt_1),其余尽量使用 not_static_icons 中对应 Lucide 图标(如 BookSearchIcon、BotMessageSquareIcon、ArrowUpRightIcon、CameraOffIcon 等)。
四、替换前后代码对比
4.1 底部导航栏(root_page.dart)
| 项目 | 替换前 | 替换后 |
|---|---|---|
| 首页 | icon: const Icon(Icons.home_outlined) / activeIcon: const Icon(Icons.home) |
icon: appHomeIcon(size: 26, color: unselectedColor, interactive: true) / activeIcon: appHomeIcon(size: 26, color: selectedColor, interactive: true) |
| 发现 | Icon(Icons.search_outlined) / Icon(Icons.search) |
appSearchIcon(size: 26, ...) |
| 消息 | Icon(Icons.message_outlined) / Icon(Icons.message) |
appMessageIcon(size: 26, ...) |
| 我的 | Icon(Icons.person_outline) / Icon(Icons.person) |
appUserIcon(size: 26, ...) |
效果:底部 Tab 切换时仍为选中/未选中颜色区分,图标在点击或悬停时可播放包自带的绘制/脉冲等动画,交互反馈更明显。
4.2 作品详情页(work_detail_page.dart)
| 位置 | 替换前 | 替换后 |
|---|---|---|
| 返回按钮 | Icon(Icons.arrow_back_ios_new, color: Colors.white) |
appArrowBackIcon(size: 24, color: Colors.white, interactive: true) |
| 收藏心形(顶部按钮) | Icon(_isFavorite ? Icons.favorite : Icons.favorite_border, color: ...) |
appHeartIcon(size: 26, color: _isFavorite ? Colors.red : Colors.white, interactive: true) |
| 双击心形动画 | Icon(Icons.favorite, size: 80, color: Colors.white) |
appHeartIcon(size: 80, color: Colors.white, interactive: false) |
| 作者占位头像 | Icon(Icons.person, color: Colors.white70) |
appUserIcon(size: 36, color: Colors.white70, interactive: false) |
| 底部点赞/收藏数 | Icon(Icons.favorite_border) / Icon(Icons.bookmark_border) |
appHeartIcon(size: 22, ...) / appBookmarkIcon(size: 22, ...) |
效果:返回、收藏等按钮在点击时有动画反馈;底部统计仍为静态展示,风格与 Lucide 统一。
4.3 首页列表/网格切换(home_page.dart)
| 替换前 | 替换后 |
|---|---|
Icon(_isGridView ? Icons.view_stream : Icons.grid_view, color: Colors.white, size: 24) |
_isGridView ? appListIcon(size: 24, color: Colors.white, interactive: true) : appGridIcon(size: 24, color: Colors.white, interactive: true) |
效果:切换列表/网格时,图标本身带动画(如 Grid2x2Icon / LayersIcon),更易感知当前模式。

4.4 我的页(profile_page.dart)
| 位置 | 替换前 | 替换后 |
|---|---|---|
| 返回 / 设置按钮 | Icon(Icons.arrow_back_ios_new) / Icon(Icons.settings_outlined) |
appArrowBackIcon(size: 24, interactive: true) / appSettingsIcon(size: 24) |
| 设置项右侧箭头 | trailing: const Icon(Icons.chevron_right) |
trailing: appChevronRightIcon(size: 22, interactive: true) |
| 获赞/收藏统计 | _StatChip(icon: Icons.favorite_border, ...) 等 |
_StatChip(iconWidget: appHeartIcon(..., color: primary, interactive: false), ...) |
| 菜单项 | _MenuItem(icon: Icons.favorite, ...) 等,leading: Icon(icon, ...),trailing: Icon(Icons.chevron_right) |
_MenuItem(iconWidget: appHeartIcon(...), ...),trailing: appChevronRightIcon(...) |
| 历史记录空态 | Icon(Icons.history, size: 64, color: Colors.grey[400]) |
appHistoryIcon(size: 64, color: Colors.grey[400], interactive: false) |
| 图片占位/失败 | Icon(Icons.image_not_supported) |
appImageOffIcon(size: 24, interactive: false) |
效果:列表项与设置项在点击时箭头/心形等有动画;统计与空态为静态图标,风格统一。
4.5 收藏页(favorites_page.dart)
| 位置 | 替换前 | 替换后 |
|---|---|---|
| 空态 | Icon(Icons.favorite_border, size: 64, color: Colors.grey[400]) |
appHeartIcon(size: 64, color: Colors.grey[400], interactive: false) |
| 返回 / 列表项箭头、占位图 | 同上模式 | appArrowBackIcon / appChevronRightIcon / appImageOffIcon |
4.6 发现页(search_page.dart)
| 位置 | 替换前 | 替换后 |
|---|---|---|
| 搜索框前缀 | prefixIcon: Icon(Icons.search, color: Colors.grey[600], size: 22) |
prefixIcon: appSearchIcon(size: 22, color: Colors.grey[600], interactive: false) |
| 刷新 | Icon(Icons.refresh) |
appRefreshIcon(size: 24, interactive: true) |
| 无结果空态 | Icon(Icons.search_off, size: 64, ...) |
appSearchIcon(size: 64, color: Colors.grey[400], interactive: false) |
| 卡片封面占位 / 头像占位 / 收藏心形 | Icon(Icons.image_not_supported) / Icon(Icons.person, ...) / Icon(isFavorite ? Icons.favorite : Icons.favorite_border, ...) |
appImageOffIcon / appUserIcon / appHeartIcon |
4.7 消息页(messages_page.dart)
| 位置 | 替换前 | 替换后 |
|---|---|---|
| 添加会话 | Icon(Icons.person_add_alt_1) |
appUserPlusIcon(size: 24)(Material 兜底) |
| 空态 | Icon(Icons.chat_bubble_outline, size: 64, ...) |
appMessageIcon(size: 64, color: Colors.grey[400], interactive: false) |
| 发送按钮 | icon: const Icon(Icons.send) |
icon: appSendIcon(size: 24, color: Colors.white, interactive: true) |
| 返回 | Icon(Icons.arrow_back_ios_new) |
appArrowBackIcon(size: 24, interactive: true) |
4.8 网络图片加载失败(network_image_widget.dart)
| 替换前 | 替换后 |
|---|---|
const Icon(Icons.error_outline, color: Colors.white, size: 50) |
appCircleAlertIcon(size: 50, color: Colors.white, interactive: false) |
效果:加载失败时显示带轻微动画的警示图标,风格与全局一致。
五、效果
| 维度 | 替换前 | 替换后 |
|---|---|---|
| 视觉 | 全部为 Material 静态图标 | 主要为 Lucide 风格线型图标,部分带绘制/脉冲/旋转等动画 |
| 交互 | 仅点击跳转或状态变化,图标本身无动效 | 底部 Tab、返回、收藏、刷新、发送、列表项等处的图标在点击或悬停时可播放动画,反馈更明确 |
| 一致性 | Material 与系统风格一致 | 全应用统一为 Lucide 系风格,仅少数(如设置、添加用户)保留 Material |
| 性能 | 字体图标,体量小 | not_static_icons 为 SVG 动画,按需使用;未增加 Rive/Lottie 等重依赖 |
鸿蒙app动态图标使用效果
六、使用提醒
- 放在可点击容器内时一律用
interactive: false:当图标作为BottomNavigationBarItem、IconButton、ListTile的 leading/trailing、或GestureDetector子节点时,必须设interactive: false,否则图标内部的手势会拦截点击,导致 Tab 切换失效、按钮/列表项无反应。修复后 Tab 与各类按钮点击均正常。 - 纯展示(空态、占位、统计小图标):
interactive: false,不响应触摸,仅展示静态或初始帧。 - 尺寸与颜色:通过
app_icons.dart各方法的size、color统一控制,与页面主题色配合(如Theme.of(context).colorScheme.primary)。 - 新增图标:优先在
app_icons.dart中增加封装,若 not_static_icons 无合适图标再用Icon(Icons.xxx)并注明原因。
七、参考链接
结束语
感谢阅读本帖,如对贴中内容有意见和建议的,欢迎与我联系交流,也欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
更多推荐




所有评论(0)