在这里插入图片描述

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

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐