基础入门 Flutter for OpenHarmony:ExpansionTile 可展开项组件详解

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
🎯 欢迎来到 Flutter for OpenHarmony 社区!本文将深入讲解 Flutter 中 ExpansionTile 可展开项组件的使用方法,带你从基础到精通,掌握这一实用的折叠展开组件。
一、ExpansionTile 组件概述
在 Flutter for OpenHarmony 应用开发中,ExpansionTile(可展开项)是一种可以展开和收起的列表项,常用于显示层级结构信息、FAQ 列表、设置选项等。用户点击后可以查看更多详细内容。
📋 ExpansionTile 组件特点
| 特点 | 说明 |
|---|---|
| 折叠展开 | 支持点击展开和收起 |
| 动画效果 | 展开收起有流畅动画 |
| 自定义头部 | 可自定义标题和图标 |
| 灵活内容 | 展开后可放置任意组件 |
| 嵌套支持 | 支持多层嵌套 |
💡 使用场景:ExpansionTile 常用于 FAQ 常见问题、设置菜单、分类列表、层级信息展示等场景。
二、ExpansionTile 基础用法
2.1 最简单的 ExpansionTile
最基础的 ExpansionTile 只需要 title 参数。
ExpansionTile(
title: const Text('点击展开'),
children: const [
ListTile(title: Text('子项 1')),
ListTile(title: Text('子项 2')),
],
)
代码解析:
title:折叠时显示的标题children:展开后显示的子组件列表- 点击标题区域即可展开或收起
2.2 完整示例
class ExpansionTileExample extends StatefulWidget {
const ExpansionTileExample({super.key});
State<ExpansionTileExample> createState() => _ExpansionTileExampleState();
}
class _ExpansionTileExampleState extends State<ExpansionTileExample> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ExpansionTile 示例')),
body: ListView(
children: [
ExpansionTile(
title: const Text('Flutter'),
subtitle: const Text('跨平台移动开发框架'),
leading: const Icon(Icons.code),
children: const [
ListTile(title: Text('Dart 语言')),
ListTile(title: Text('Widget 系统')),
ListTile(title: Text('状态管理')),
],
),
ExpansionTile(
title: const Text('React Native'),
subtitle: const Text('使用 JavaScript 开发原生应用'),
leading: const Icon(Icons.web),
children: const [
ListTile(title: Text('JavaScript')),
ListTile(title: Text('React')),
ListTile(title: Text('Bridge')),
],
),
],
),
);
}
}
⚠️ 注意事项:ExpansionTile 通常放在 ListView 或 Column 中使用,确保有足够的空间展示展开内容。
三、ExpansionTile 常用属性
3.1 title - 标题
设置折叠时显示的主标题。
ExpansionTile(
title: const Text('主标题'),
children: const [ListTile(title: Text('内容'))],
)
深入理解:title 是用户点击的主要区域,建议使用简洁明了的文字。
3.2 subtitle - 副标题
设置折叠时显示的副标题,提供额外信息。
ExpansionTile(
title: const Text('Flutter'),
subtitle: const Text('跨平台移动开发框架'),
children: const [ListTile(title: Text('内容'))],
)
使用技巧:subtitle 可以用来展示更多描述性信息,帮助用户理解内容。
3.3 leading - 前置图标
在标题左侧显示的图标。
ExpansionTile(
leading: const Icon(Icons.folder),
title: const Text('文件夹'),
children: const [ListTile(title: Text('文件1'))],
)
视觉效果:leading 图标固定显示,不会随展开收起而改变方向。
3.4 trailing - 后置图标
在标题右侧显示的图标,默认是展开/收起箭头。
ExpansionTile(
title: const Text('自定义图标'),
trailing: const Icon(Icons.arrow_forward),
children: const [ListTile(title: Text('内容'))],
)
注意:自定义 trailing 后,箭头的旋转动画会失效。如果需要保留动画效果,不要自定义 trailing。
3.5 children - 子组件列表
展开后显示的内容列表。
ExpansionTile(
title: const Text('展开内容'),
children: [
ListTile(
leading: const Icon(Icons.star),
title: const Text('选项1'),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.favorite),
title: const Text('选项2'),
onTap: () {},
),
],
)
使用建议:
- 使用 ListTile 作为子项,保持一致的样式
- 可以为子项添加点击事件
- 支持嵌套 ExpansionTile
3.6 initiallyExpanded - 初始展开状态
设置是否默认展开。
ExpansionTile(
title: const Text('默认展开'),
initiallyExpanded: true,
children: const [ListTile(title: Text('内容'))],
)
3.7 onExpansionChanged - 展开状态改变回调
监听展开和收起事件。
ExpansionTile(
title: const Text('监听状态'),
onExpansionChanged: (bool expanded) {
print('当前状态: ${expanded ? "展开" : "收起"}');
},
children: const [ListTile(title: Text('内容'))],
)
3.8 tilePadding - 标题内边距
设置标题区域的内边距。
ExpansionTile(
title: const Text('自定义内边距'),
tilePadding: const EdgeInsets.symmetric(horizontal: 20),
children: const [ListTile(title: Text('内容'))],
)
📊 ExpansionTile 属性速查表
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title |
Widget | - | 标题(必填) |
subtitle |
Widget? | - | 副标题 |
leading |
Widget? | - | 前置图标 |
trailing |
Widget? | - | 后置图标 |
children |
List | [] | 子组件列表 |
initiallyExpanded |
bool | false | 初始展开状态 |
onExpansionChanged |
ValueChanged? | - | 展开状态改变回调 |
tilePadding |
EdgeInsetsGeometry? | - | 标题内边距 |
四、ExpansionTile 样式定制
4.1 自定义颜色
ExpansionTile(
title: const Text('自定义颜色'),
iconColor: Colors.blue,
collapsedIconColor: Colors.grey,
textColor: Colors.black,
collapsedTextColor: Colors.grey,
children: const [ListTile(title: Text('内容'))],
)
属性说明:
iconColor:展开状态下的图标颜色collapsedIconColor:折叠状态下的图标颜色textColor:展开状态下的文字颜色collapsedTextColor:折叠状态下的文字颜色
4.2 自定义圆角和背景
使用 Container 包裹 ExpansionTile 并设置样式。
Container(
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
),
],
),
child: ExpansionTile(
title: const Text('卡片样式'),
children: const [ListTile(title: Text('内容'))],
),
)
应用场景:适合需要突出显示的 ExpansionTile,增强视觉效果。
4.3 使用主题样式
ExpansionTileTheme(
data: ExpansionTileThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
backgroundColor: Colors.grey[100],
iconColor: Colors.blue,
),
child: ExpansionTile(
title: const Text('主题样式'),
children: const [ListTile(title: Text('内容'))],
),
)
设计建议:在需要统一样式的多个 ExpansionTile 时使用主题。
五、ExpansionTile 嵌套使用
ExpansionTile 支持多层嵌套,用于展示层级结构。
5.1 二级嵌套
ExpansionTile(
title: const Text('编程语言'),
children: [
ExpansionTile(
title: const Text('前端'),
children: const [
ListTile(title: Text('HTML')),
ListTile(title: Text('CSS')),
ListTile(title: Text('JavaScript')),
],
),
ExpansionTile(
title: const Text('后端'),
children: const [
ListTile(title: Text('Java')),
ListTile(title: Text('Python')),
ListTile(title: Text('Node.js')),
],
),
],
)
5.2 三级嵌套
ExpansionTile(
title: const Text('Flutter 学习路径'),
children: [
ExpansionTile(
title: const Text('基础阶段'),
children: [
ExpansionTile(
title: const Text('Dart 语言'),
children: const [
ListTile(title: Text('变量和类型')),
ListTile(title: Text('函数')),
ListTile(title: Text('类和对象')),
],
),
ListTile(title: Text('Widget 基础')),
ListTile(title: Text('布局组件')),
],
),
ExpansionTile(
title: const Text('进阶阶段'),
children: const [
ListTile(title: Text('状态管理')),
ListTile(title: Text('网络请求')),
ListTile(title: Text('数据持久化')),
],
),
],
)
使用技巧:
- 嵌套层次不宜过深(建议不超过 3 层)
- 为每层设置不同的标题样式
- 考虑使用图标区分不同层级
六、ExpansionTile 实际应用场景
6.1 FAQ 常见问题
class FAQPage extends StatelessWidget {
final List<Map<String, String>> faqs = [
{
'question': '什么是 Flutter?',
'answer': 'Flutter 是 Google 推出的跨平台移动开发框架。',
},
{
'question': 'Flutter 使用什么语言?',
'answer': 'Flutter 使用 Dart 语言进行开发。',
},
{
'question': 'Flutter 支持哪些平台?',
'answer': 'Flutter 支持 iOS、Android、Web、桌面等平台。',
},
];
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('常见问题')),
body: ListView.builder(
itemCount: faqs.length,
itemBuilder: (context, index) {
return ExpansionTile(
title: Text(faqs[index]['question']!),
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Text(faqs[index]['answer']!),
),
],
);
},
),
);
}
}
设计要点:
- 使用 ListView.builder 动态生成
- 为答案添加适当的内边距
- 问题使用明确的问句格式
6.2 设置菜单
ExpansionTile(
title: const Text('通知设置'),
leading: const Icon(Icons.notifications),
children: [
SwitchListTile(
title: const Text('推送通知'),
subtitle: const Text('接收应用推送消息'),
value: true,
onChanged: (value) {},
),
SwitchListTile(
title: const Text('声音提醒'),
subtitle: const Text('新消息时播放声音'),
value: true,
onChanged: (value) {},
),
SwitchListTile(
title: const Text('震动反馈'),
subtitle: const Text('触感震动'),
value: false,
onChanged: (value) {},
),
],
)
最佳实践:
- 使用 SwitchListTile 作为子项
- 为每个选项添加说明文字
- 保持设置选项的简洁性
6.3 分类列表
ExpansionTile(
title: const Text('电子产品'),
leading: const Icon(Icons.devices),
children: [
ListTile(
leading: const Icon(Icons.phone),
title: const Text('手机'),
trailing: const Text('1200元'),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.laptop),
title: const Text('笔记本'),
trailing: const Text('5000元'),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.tablet),
title: const Text('平板'),
trailing: const Text('3000元'),
onTap: () {},
),
],
)
七、完整示例代码
import 'package:flutter/material.dart';
void main() {
runApp(const ExpansionTileDemo());
}
class ExpansionTileDemo extends StatelessWidget {
const ExpansionTileDemo({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'ExpansionTile 组件演示',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.light(
primary: const Color(0xFF6366F1),
secondary: const Color(0xFF8B5CF6),
surface: const Color(0xFFE8EAF6),
background: const Color(0xFFF8F9FF),
brightness: Brightness.light,
),
useMaterial3: true,
),
home: const ExpansionTilePage(),
);
}
}
class ExpansionTilePage extends StatefulWidget {
const ExpansionTilePage({super.key});
State<ExpansionTilePage> createState() => _ExpansionTilePageState();
}
class _ExpansionTilePageState extends State<ExpansionTilePage> {
final List<Map<String, dynamic>> _faqs = [
{
'question': '什么是 Flutter?',
'answer': 'Flutter 是 Google 推出的跨平台移动开发框架,使用 Dart 语言编写,可以同时构建 iOS、Android、Web 等多个平台的应用。',
'icon': Icons.info,
'color': Colors.blue,
},
{
'question': 'Flutter 的优势是什么?',
'answer': 'Flutter 具有高性能、快速开发、单一代码库、丰富的 UI 组件、热重载等优势,能够显著提高开发效率。',
'icon': Icons.star,
'color': Colors.orange,
},
{
'question': 'Flutter 支持哪些平台?',
'answer': 'Flutter 支持 iOS、Android、Web、Windows、macOS、Linux 等多个平台,真正实现了一次编写,到处运行。',
'icon': Icons.devices,
'color': Colors.green,
},
{
'question': '如何学习 Flutter?',
'answer': '学习 Flutter 可以从 Dart 语言基础开始,然后学习 Widget 系统、布局组件、状态管理等,最后通过实践项目来巩固知识。',
'icon': Icons.school,
'color': Colors.purple,
},
];
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xFFE8F4FF),
Color(0xFFF8F9FF),
Color(0xFFE8F4FF),
],
),
),
child: SafeArea(
child: Column(
children: [
// 标题区域
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF6366F1),
Color(0xFF8B5CF6),
Color(0xFFEC4899),
],
),
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24),
),
boxShadow: [
BoxShadow(
color: const Color(0xFF6366F1).withOpacity(0.3),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: const Column(
children: [
Text(
'📂 ExpansionTile',
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 8),
Text(
'探索 Flutter for OpenHarmony 中可展开项组件的各种用法',
style: TextStyle(
fontSize: 16,
color: Colors.white,
),
),
],
),
),
const SizedBox(height: 24),
// FAQ 列表
Expanded(
child: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 20),
itemCount: _faqs.length,
itemBuilder: (context, index) {
final faq = _faqs[index];
return Container(
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 20,
offset: const Offset(0, 4),
),
],
),
child: Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
expansionTileTheme: ExpansionTileThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
),
),
child: ExpansionTile(
leading: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: faq['color'].withOpacity(0.1),
borderRadius: BorderRadius.circular(10),
),
child: Icon(
faq['icon'],
color: faq['color'],
size: 24,
),
),
title: Text(
faq['question'],
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFF1E293B),
),
),
iconColor: faq['color'],
collapsedIconColor: const Color(0xFF94A3B8),
textColor: faq['color'],
collapsedTextColor: const Color(0xFF64748B),
children: [
Padding(
padding: const EdgeInsets.all(20),
child: Text(
faq['answer'],
style: const TextStyle(
fontSize: 14,
color: Color(0xFF475569),
height: 1.6,
),
),
),
],
),
),
);
},
),
),
],
),
),
),
);
}
}
八、总结
ExpansionTile 是 Flutter for OpenHarmony 中实现折叠展开功能的重要组件,通过合理使用可以创建层次分明的信息展示界面。
🎯 核心要点
- 基础用法:设置 title 和 children 即可
- 样式定制:通过颜色、图标、圆角等自定义外观
- 嵌套支持:支持多层嵌套展示层级结构
- 状态监听:onExpansionChanged 监听展开收起
- 灵活应用:适用于 FAQ、设置、分类等多种场景
📚 使用建议
| 场景 | 推荐方案 |
|---|---|
| FAQ 列表 | 使用 ListView.builder 动态生成 |
| 设置菜单 | 结合 SwitchListTile 使用 |
| 分类列表 | 添加 leading 图标和 trailing 价格 |
| 层级结构 | 使用嵌套 ExpansionTile |
| 统一样式 | 使用 ExpansionTileTheme |
掌握 ExpansionTile 组件后,你可以轻松创建专业的折叠展开界面,为用户提供清晰有序的信息浏览体验。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)