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

Flutter中如何调整折叠状态下ExpansionTile的上下内边距

解决ExpansionTile仅折叠状态下调整上下内边距的问题

核心方案:利用状态动态控制内边距

你已经在onExpansionChanged里维护了isExpanded变量,直接用它来动态切换tilePadding的上下值即可,完全不用套Container——这样只会在折叠时压缩内边距,展开时自动恢复原有的空间。

另外你在title里嵌套了ListTile,ListTile本身自带默认上下内边距,这也是空间浪费的原因之一,可以通过visualDensity进一步压缩,或者直接替换成自定义Row彻底控制布局。

修改后的完整代码

Widget additiveCard(
  BuildContext context, List<FoodAdditive> additives, Product product, bool good) {
  String subtitleText = good ? "השפעה נמוכה" : "השפעה גבוהה";

  return Theme(
    data: Theme.of(context).copyWith(
      dividerColor: Colors.transparent,
    ),
    child: ExpansionTile(
      // 关键:根据展开状态动态设置上下内边距
      tilePadding: EdgeInsets.symmetric(
        horizontal: 16,
        // 折叠时上下内边距设为4,展开时用默认的16(可自行调整数值)
        vertical: isExpanded ? 16 : 4,
      ),
      onExpansionChanged: (bool expanding) {
        setState(() => isExpanded = expanding);
        isExpanded ? _controller.forward() : _controller.reverse();
      },
      title: Row(
        children: [
          Expanded(
            // 优化:压缩ListTile内部的默认间距
            child: ListTile(
              contentPadding: EdgeInsets.zero,
              visualDensity: VisualDensity(vertical: -4),
              title: Text(
                getTitle("תוספים"),
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              leading: Icon(Icons.science),
              subtitle: Text(subtitleText),
            ),
          ),
          Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              buildRatingCircle(16, good ? Colors.green : Colors.red),
            ],
          ),
        ],
      ),
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Align(
            alignment: Alignment.centerRight,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.end,
              children: product
                  .countAdditivesByRating(additives)
                  .entries
                  .where((entry) => entry.value > 0)
                  .map((entry) {
                    int rating = entry.key;
                    int ratingCount = entry.value;
                    return buildAdditiveCircle(16, ratingCount, rating);
                  })
                  .toList()
                  .reversed
                  .toList(),
            ),
          ),
        ),
      ],
    ),
  );
}

关键修改说明

  1. 动态tilePadding:通过isExpanded判断,折叠时把上下内边距设为你想要的小值(比如4),展开时恢复默认的16(或你需要的展开状态间距)
  2. 压缩ListTile内部间距:添加visualDensity: VisualDensity(vertical: -4),数值越小(负数),ListTile内部的上下留白越少
  3. 移除无效嵌套:删掉了children里Align下多余的Expanded(Expanded必须在Row/Column/Flex容器内才生效)

替代方案:完全自定义标题行

如果想彻底摆脱ListTile的默认间距限制,可以把内部的ListTile换成自定义Row,完全控制每个元素的间距:

// 替换title里的Expanded(child: ListTile(...))为:
Expanded(
  child: Row(
    children: [
      Icon(Icons.science, size: 24),
      SizedBox(width: 16),
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          mainAxisSize: MainAxisSize.min, // 仅占用内容高度,无多余留白
          children: [
            Text(
              getTitle("תוספים"),
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 2), // 自定义标题和副标题的间距
            Text(subtitleText),
          ],
        ),
      ),
    ],
  ),
)

这种方式可以实现极致的空间控制,没有任何默认留白。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:05:26