应用市场大部分热门榜单应用都是在设计视觉上下功夫,这次计划优化下页面中的图标,使用动态图标来提升下美感。

欢迎加入开源鸿蒙跨平台社区: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

  • 对外提供一组方法:appArrowBackIconappHeartIconappBookmarkIconappHomeIconappSearchIconappMessageIconappUserIconappChevronRightIconappSettingsIconappHistoryIconappLogOutIconappRefreshIconappUserPlusIconappSendIconappImageOffIconappCircleAlertIconappGridIconappListIcon 等。
  • 每个方法支持 sizecolorinteractive、部分支持 controller;默认动画时长 400ms。
  • 设置添加用户 等包内无合适图标时使用 Material Icons(如 Icons.settings_outlinedIcons.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动态图标使用效果

六、使用提醒

  1. 放在可点击容器内时一律用 interactive: false:当图标作为 BottomNavigationBarItemIconButtonListTile 的 leading/trailing、或 GestureDetector 子节点时,必须设 interactive: false,否则图标内部的手势会拦截点击,导致 Tab 切换失效、按钮/列表项无反应。修复后 Tab 与各类按钮点击均正常。
  2. 纯展示(空态、占位、统计小图标):interactive: false,不响应触摸,仅展示静态或初始帧。
  3. 尺寸与颜色:通过 app_icons.dart 各方法的 sizecolor 统一控制,与页面主题色配合(如 Theme.of(context).colorScheme.primary)。
  4. 新增图标:优先在 app_icons.dart 中增加封装,若 not_static_icons 无合适图标再用 Icon(Icons.xxx) 并注明原因。

七、参考链接

结束语

感谢阅读本帖,如对贴中内容有意见和建议的,欢迎与我联系交流,也欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐