在这里插入图片描述

欢迎加入开源鸿蒙跨平台社区: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 组件后,你可以轻松创建专业的折叠展开界面,为用户提供清晰有序的信息浏览体验。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐