You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter ExpansionTile双操作配置及尾随图标隐藏问题

解决ExpansionTile的两个自定义需求

一、实现点击尾随图标展开,点击其他区域跳转

ExpansionTile默认点击整个tile都会触发展开/收起,要区分点击区域得这么改:

  • 给每个tile维护独立的展开状态变量_isExpanded
  • 把leading、title、subtitle包装成可点击区域,点击时执行跳转逻辑
  • 自定义trailing图标,点击这个图标单独切换展开状态,同时将ExpansionTile的expanded属性绑定到状态变量上

二、子项为空时隐藏尾随图标

直接判断子列表长度:如果长度为0,就把trailing设为空组件(比如SizedBox.shrink());否则显示切换展开的图标。

修改后的完整代码

Expanded(
  child: ListView.builder(
    itemBuilder: (context, index) {
      // 每个tile独立维护展开状态
      bool _isExpanded = false;
      final sublist = list[index].sublist;
      return Card(
        child: StatefulBuilder(
          builder: (context, setState) {
            return ExpansionTile(
              // 绑定展开状态
              expanded: _isExpanded,
              // 把leading/title/subtitle整合成可点击区域,点击跳转
              leading: GestureDetector(
                onTap: () {
                  // 替换成你的跳转逻辑,比如Navigator.push
                  print('跳转至目标页面');
                },
                child: Image.asset('images'),
              ),
              title: GestureDetector(
                onTap: () {
                  print('跳转至目标页面');
                },
                child: Text('Text'),
              ),
              subtitle: GestureDetector(
                onTap: () {
                  print('跳转至目标页面');
                },
                child: Text('Text'),
              ),
              // 根据子列表长度决定是否显示尾随图标
              trailing: sublist.isEmpty
                  ? const SizedBox.shrink()
                  : IconButton(
                      icon: Icon(
                        _isExpanded ? Icons.expand_less : Icons.expand_more,
                      ),
                      onPressed: () {
                        setState(() {
                          _isExpanded = !_isExpanded;
                        });
                      },
                    ),
              // 子列表为空时直接传空数组
              children: sublist.isEmpty
                  ? []
                  : [
                      ListView.builder(
                        itemBuilder: (context, index2) {
                          return Card(
                            child: ListTile(
                              onTap: () => print('test'),
                              leading: Image.asset('images'),
                              title: Text('Text'),
                              subtitle: Text('Text'),
                            ),
                          );
                        },
                        itemCount: sublist.length,
                        shrinkWrap: true,
                        padding: const EdgeInsets.all(5),
                        scrollDirection: Axis.vertical,
                      ),
                    ],
            );
          },
        ),
      );
    },
    itemCount: list.length,
    shrinkWrap: true,
    padding: const EdgeInsets.all(5),
    scrollDirection: Axis.vertical,
  ),
)

额外优化提示

如果觉得多个GestureDetector重复,可以把leading、title、subtitle整个包裹在一个大的GestureDetector里,这样点击tile除尾随图标外的所有区域都会触发跳转,代码更简洁。

内容的提问来源于stack exchange,提问作者Icaroto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:30:57