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

Flutter中为Stateful Widget添加下拉显隐动画及移除多余间距

问题解决:为Flutter下拉容器添加动画并移除多余间距

核心需求

  • 为控制显隐的Container添加类似下拉菜单的平滑过渡动画
  • 移除Divider与Container之间的多余间距
  • 当前使用GetX的obs状态管理,仅了解AnimatedContainer,不确定具体实现方式

解决方案

1. 实现下拉显隐动画

AnimatedContainer完全适用,结合GetX的状态监听即可实现自然的下拉动画:

  • 隐藏时设置高度为0,显示时设为double.infinity让容器自适应内容高度
  • 添加clipBehavior: Clip.hardEdge避免内容溢出
  • 使用Curves.easeInOut曲线实现流畅的过渡效果

2. 移除多余间距

原布局的间隙来自Widget默认的布局间距,只需两步即可消除:

  • 给Divider设置height: 1,取消其默认的上下留白
  • 给Container设置margin: EdgeInsets.only(top: 0),彻底消除与Divider的间距

修改后的完整代码

主Widget代码片段

Padding(
  padding: const EdgeInsets.only(left: 22.0, right: 22.0, top: 15.0, bottom: 5.0),
  child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: [
      Text(
        'Job details ',
        style: GoogleFonts.poppins(
            fontSize: 16,
            fontWeight: FontWeight.w600,
            color: Color(0xff34495E)),
      ),
      IconButton(
        onPressed: controller.toggleDropDownVisibility,
        icon: Obx(() => Icon(
              controller.isDropDownVisible.value
                  ? Icons.expand_less
                  : Icons.expand_more,
              color: Color(0xff3498DB),
            )),
      )
    ],
  ),
),
Divider(
  color: Color(0xff34495E).withOpacity(0.1),
  thickness: 2,
  height: 1, // 消除Divider默认上下间距
),
Obx(() => AnimatedContainer(
      duration: Duration(milliseconds: 300),
      curve: Curves.easeInOut,
      height: controller.isDropDownVisible.value ? double.infinity : 0,
      clipBehavior: Clip.hardEdge,
      margin: EdgeInsets.only(top: 0),
      color: Color(0xffF5F5F5),
      child: Padding(
        padding: const EdgeInsets.only(left: 22.0, right: 22),
        child: Table(
          border: TableBorder(
            horizontalInside: BorderSide(
              strokeAlign: 10,
              color: Color(0xff34495E).withOpacity(0.1),
            ),
          ),
          defaultColumnWidth: const IntrinsicColumnWidth(),
          children: [
            TableRow(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Title',
                    style: GoogleFonts.poppins(
                        fontSize: 10,
                        fontWeight: FontWeight.w400,
                        fontStyle: FontStyle.italic,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Asoebi Gown',
                    style: GoogleFonts.poppins(
                        fontSize: 12,
                        fontWeight: FontWeight.w400,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
              ],
            ),
            TableRow(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Quantity',
                    style: GoogleFonts.poppins(
                        fontSize: 10,
                        fontWeight: FontWeight.w400,
                        fontStyle: FontStyle.italic,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    '12',
                    style: GoogleFonts.poppins(
                        fontSize: 12,
                        fontWeight: FontWeight.w400,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
              ],
            ),
            TableRow(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Description',
                    style: GoogleFonts.poppins(
                        fontSize: 10,
                        fontWeight: FontWeight.w400,
                        fontStyle: FontStyle.italic,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Praesent vitae neque porta, hendrerit enim sed, temps ante. Suspendisse vitae massa neque. Praesent vitae neque porta, hendrerit enim sed, tempus ante.',
                    style: GoogleFonts.poppins(
                        fontSize: 12,
                        fontWeight: FontWeight.w400,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
              ],
            ),
            TableRow(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Phone',
                    style: GoogleFonts.poppins(
                        fontSize: 10,
                        fontWeight: FontWeight.w400,
                        fontStyle: FontStyle.italic,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    '09077338833',
                    style: GoogleFonts.poppins(
                        fontSize: 12,
                        fontWeight: FontWeight.w400,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
              ],
            ),
            TableRow(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Text(
                    'Date to complete',
                    style: GoogleFonts.poppins(
                        fontSize: 10,
                        fontWeight: FontWeight.w400,
                        fontStyle: FontStyle.italic,
                        color: Color(0xff34495E).withOpacity(0.8)),
                  ),
                ),
                TableCell(
                    verticalAlignment:
                        TableCellVerticalAlignment.fill,
                    child: Row(
                      crossAxisAlignment:
                          CrossAxisAlignment.center,
                      mainAxisAlignment:
                          MainAxisAlignment.spaceBetween,
                      children: [
                        Padding(
                          padding: EdgeInsets.all(8.0),
                          child: Text(
                            '05-03-22',
                            style: GoogleFonts.poppins(
                                fontSize: 12,
                                fontWeight: FontWeight.w400,
                                color: Color(0xff34495E)
                                    .withOpacity(0.8)),
                          ),
                        ),
                        Container(
                          decoration: BoxDecoration(
                            color: Color.fromRGBO(
                                50, 151, 219, 0.09),
                            borderRadius:
                                BorderRadius.circular(20),
                          ),
                          child: Padding(
                            padding:
                                const EdgeInsets.all(8.0),
                            child: Text(
                              '15 days',
                              style: GoogleFonts.poppins(
                                  fontSize: 10,
                                  fontWeight:
                                      FontWeight.w400,
                                  fontStyle:
                                      FontStyle.italic,
                                  color: Color(0xff34495E)),
                            ),
                          ),
                        ),
                      ],
                    )),
              ],
            ),
          ],
        ),
      ),
    )),

GetX控制器代码(无需修改)

final isDropDownVisible = false.obs;

void toggleDropDownVisibility() {
  isDropDownVisible.value = !isDropDownVisible.value;
}

关键优化点说明

  • 移除冗余的setState,直接通过GetX的Obx监听状态更新UI
  • 将两个IconButton合并为一个,动态切换图标简化代码
  • 通过Divider的height和Container的margin彻底消除布局间隙
  • 利用AnimatedContainer的高度过渡实现原生下拉动画效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 19:25:29