Flutter 鸿蒙跨平台折叠式列表实践
在鸿蒙(HarmonyOS)开发中,针对折叠屏和平板的适配是必修课。折叠屏的动态尺寸变化、多窗口模式,以及平板的大屏交互逻辑,都要求界面具备灵活的响应式能力和流畅的动效反馈。本文将带你通过Flutter构建一个具有 “折叠展开” 动画效果的分类管理应用,学习如何集成三方库provider进行跨组件状态联动,并使用animations库实现符合鸿蒙设计风格的丝流动效,最终实现一套能在鸿蒙 Next
Flutter 鸿蒙跨平台折叠式列表实践
Flutter 鸿蒙开发实践:利用三方库实现跨端流式折叠列表与状态联动
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
1. 前言
在鸿蒙(HarmonyOS) 开发中,针对折叠屏和平板的适配是必修课。折叠屏的动态尺寸变化、多窗口模式,以及平板的大屏交互逻辑,都要求界面具备灵活的响应式能力和流畅的动效反馈。本文将带你通过 Flutter 构建一个具有 “折叠展开” 动画效果的分类管理应用,学习如何集成三方库 provider 进行跨组件状态联动,并使用 animations 库实现符合鸿蒙设计风格的丝流动效,最终实现一套能在鸿蒙 Next 虚拟机上流畅运行的跨端交互方案。
2. 核心关键词
-
Flutter: 跨端 UI 框架,一套代码可运行于鸿蒙、Android、iOS 等多端。
-
三方库:
-
provider: 轻量级状态管理库,简化跨组件状态共享与更新。 -
animations: Flutter 官方动效库,提供鸿蒙风格的隐式动画(如折叠、缩放、过渡)。
-
-
鸿蒙: HarmonyOS Next 虚拟机运行环境,适配折叠屏 / 平板的交互与渲染特性。
3. 项目案例:折叠式分类面板
3.1 需求说明
实现一个类似鸿蒙系统设置的分类面板:
-
初始状态下仅展示分类标题(如 “网络设置”“设备管理”);
-
点击分类标题,以流式折叠动画展开该分类下的详细配置项;
-
再次点击则收起,所有分类的展开 / 收起状态全局联动;
-
适配鸿蒙折叠屏的尺寸变化,展开 / 收起动效无卡顿。
3.2 最终效果预览
| 状态 | 效果描述 |
|---|---|
| 初始状态 | 仅显示所有分类标题,面板高度紧凑 |
| 展开状态 | 目标分类平滑展开,显示子配置项 |
| 折叠状态 | 展开的分类以反向动画收起,恢复紧凑 |
| 尺寸适配 | 折叠屏开合时,面板布局自动适配 |
4. 环境与依赖配置
4.1 基础环境
-
Flutter 版本:3.16+(兼容鸿蒙 Next 虚拟机)
-
鸿蒙 SDK:API 9+(HarmonyOS Next 开发者预览版)
-
开发工具:DevEco Studio 4.0+ / VS Code
4.2 依赖引入
在项目根目录的 pubspec\.yaml 中添加以下依赖:
dependencies:
flutter:
sdk: flutter
# 状态管理:跨组件共享展开/收起状态
provider: ^6.1.1
# 动效库:提供鸿蒙风格的折叠动画
animations: ^2.0.11
# 鸿蒙适配:基础 UI 组件兼容
harmony_widgets: ^1.0.0 # 鸿蒙官方 Flutter 适配库
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
添加完成后执行 flutter pub get 安装依赖。
5. 核心实现步骤
5.1 状态管理:定义全局折叠状态
通过 provider 定义一个全局状态类,管理所有分类的展开 / 收起状态:
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
// 分类模型
class CategoryModel {
final String id; // 分类唯一标识
final String title; // 分类标题
final List<String> items; // 分类下的子项
bool isExpanded; // 是否展开
CategoryModel({
required this.id,
required this.title,
required this.items,
this.isExpanded = false,
});
}
// 全局折叠状态管理
class ExpandStateProvider with ChangeNotifier {
// 所有分类的状态集合
final Map<String, CategoryModel> _categories = {
"network": CategoryModel(
id: "network",
title: "网络设置",
items: ["WLAN", "移动网络", "蓝牙", "VPN"],
),
"device": CategoryModel(
id: "device",
title: "设备管理",
items: ["显示与亮度", "声音与振动", "存储"],
),
"account": CategoryModel(
id: "account",
title: "账号与同步",
items: ["华为账号", "云空间", "同步设置"],
),
};
// 获取所有分类
List<CategoryModel> get categories => _categories.values.toList();
// 切换分类展开/收起状态
void toggleExpand(String categoryId) {
if (_categories.containsKey(categoryId)) {
_categories[categoryId]!.isExpanded = !_categories[categoryId]!.isExpanded;
notifyListeners(); // 通知组件刷新
}
}
}
// 提供状态上下文
Widget createExpandStateProvider({required Widget child}) {
return ChangeNotifierProvider(
create: (context) => ExpandStateProvider(),
child: child,
);
}
5.2 动画封装:鸿蒙风格折叠动效
使用 animations 库的 SizeTransition 结合鸿蒙动效曲线,封装折叠动画组件:
import 'package:animations/animations.dart';
import 'package:flutter/material.dart';
// 鸿蒙风格折叠动画组件
class HarmonyExpandAnimation extends StatelessWidget {
final bool isExpanded; // 是否展开
final Widget child; // 动画包裹的子组件
const HarmonyExpandAnimation({
super.key,
required this.isExpanded,
required this.child,
});
Widget build(BuildContext context) {
return SizeTransition(
// 鸿蒙设计规范的动画曲线:先快后慢,贴合系统动效
curve: Curves.fastOutSlowIn,
sizeFactor: AnimationController(
vsync: Navigator.of(context),
duration: const Duration(milliseconds: 300), // 鸿蒙标准动效时长
).drive(
CurveTween(curve: isExpanded ? Curves.linear : Curves.easeOut),
),
axis: Axis.vertical, // 垂直方向折叠
child: child,
);
}
}
5.3 核心 UI:折叠式分类面板
组合状态管理和动画组件,实现可交互的分类面板:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class FoldableCategoryPanel extends StatelessWidget {
const FoldableCategoryPanel({super.key});
Widget build(BuildContext context) {
// 获取全局折叠状态
final expandState = Provider.of<ExpandStateProvider>(context);
return ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: expandState.categories.length,
itemBuilder: (context, index) {
final category = expandState.categories[index];
return Container(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12), // 鸿蒙风格圆角
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 4,
offset: const Offset(0, 2),
)
],
),
child: Column(
children: [
// 分类标题栏(可点击)
InkWell(
onTap: () => expandState.toggleExpand(category.id),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
category.title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFF1A1A1A), // 鸿蒙标准文字色
),
),
// 展开/收起图标(鸿蒙风格)
Icon(
category.isExpanded
? Icons.keyboard_arrow_up_rounded
: Icons.keyboard_arrow_down_rounded,
color: const Color(0xFF666666),
),
],
),
),
),
// 折叠动画包裹的子项列表
HarmonyExpandAnimation(
isExpanded: category.isExpanded,
child: Column(
children: category.items
.map((item) => Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
child: Row(
children: [
const SizedBox(width: 8),
Text(
item,
style: const TextStyle(
fontSize: 14,
color: Color(0xFF333333),
),
),
],
),
))
.toList(),
),
),
],
),
);
},
);
}
}
5.4 入口页面:整合所有组件
在鸿蒙应用入口页面整合状态管理和面板组件:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
// 注入全局状态
return createExpandStateProvider(
child: MaterialApp(
title: '鸿蒙折叠列表 Demo',
theme: ThemeData(
// 适配鸿蒙系统主题
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.harmony: CupertinoPageTransitionsBuilder(),
},
),
),
home: const HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('鸿蒙风格折叠面板'),
backgroundColor: const Color(0xFF007DFF), // 鸿蒙标准主色
),
body: const Padding(
padding: EdgeInsets.only(top: 16),
child: FoldableCategoryPanel(),
),
);
}
}
6. 鸿蒙适配优化
6.1 折叠屏尺寸适配
监听鸿蒙折叠屏的尺寸变化,动态调整面板布局:
import 'package:flutter/material.dart';
import 'package:harmony_widgets/harmony_widgets.dart';
// 在 HomePage 中添加尺寸监听
Widget build(BuildContext context) {
return HarmonyScreenAdapt(
// 监听折叠屏状态
onScreenChange: (ScreenType type) {
if (type == ScreenType.fold) {
// 折叠状态:缩小面板内边距
setState(() => _padding = const EdgeInsets.only(top: 8));
} else {
// 展开状态:恢复默认内边距
setState(() => _padding = const EdgeInsets.only(top: 16));
}
},
child: Scaffold(
body: Padding(
padding: _padding,
child: const FoldableCategoryPanel(),
),
),
);
}
6.2 鸿蒙动效校准
调整动画时长和曲线,完全匹配鸿蒙系统动效标准:
// 修改 HarmonyExpandAnimation 中的动画配置
AnimationController(
vsync: Navigator.of(context),
duration: const Duration(milliseconds: 280), // 鸿蒙系统动效标准时长
).drive(
CurveTween(curve: isExpanded ? Curves.easeInOut : Curves.fastOutSlowIn),
),
7. 运行与测试
7.1 鸿蒙虚拟机运行
-
打开 DevEco Studio,配置 HarmonyOS Next 虚拟机;
-
在 Flutter 项目中执行
flutter run \-d harmony; -
虚拟机中即可看到带折叠动效的分类面板,点击分类可触发展开 / 收起。
7.2 测试要点
-
验证所有分类的展开 / 收起状态是否独立且联动;
-
折叠屏开合时,面板布局是否自动适配;
-
动画是否流畅无卡顿,符合鸿蒙设计风格;
-
跨组件状态更新是否及时(如点击标题后图标是否同步切换)。
8. 总结与扩展
8.1 核心知识点回顾
-
通过
provider实现了跨组件的状态共享,简化了折叠状态的管理; -
基于
animations库封装了符合鸿蒙风格的折叠动画,提升了交互体验; -
适配鸿蒙折叠屏的尺寸变化,保证了跨设备的一致性。
8.2 扩展方向
-
增加 “全部展开 / 全部收起” 按钮,批量控制分类状态;
-
接入鸿蒙原生能力,将折叠状态持久化到鸿蒙系统设置;
-
扩展子项的交互能力(如点击子项跳转到对应设置页面);
-
适配鸿蒙多窗口模式,支持面板拖拽缩放。
8.3 注意事项
-
鸿蒙 Next 虚拟机的 Flutter 适配仍在迭代,需保持 Flutter 版本与鸿蒙 SDK 兼容;
-
动效时长需严格遵循鸿蒙设计规范,避免过度动画影响体验;
-
状态管理中需注意性能优化,避免频繁 notifyListeners 导致的卡顿。
9. 参考资料
-
Flutter 官方文档:https://flutter.dev/docs
-
HarmonyOS Next 开发者文档:https://developer.harmonyos.com/
-
provider 库文档:https://pub.dev/packages/provider
-
animations 库文档:https://pub.dev/packages/animations
运行截图:
更多推荐
所有评论(0)