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

Flutter GetX底部弹窗高度调整与Controller释放问题求解

问题根源
  • Get.bottomSheet唤起的弹窗属于GetX路由栈管控范围,弹窗关闭时GetX会自动回收绑定的Controller实例,符合内存管理预期,但默认配置下弹窗容器会撑满最大可用高度,默认用法无法直接自定义高度。
  • 原生showModalBottomSheet唤起的弹窗属于Flutter框架路由管控范围,不在GetX路由监听链路内,GetX无法感知弹窗销毁事件,不会自动回收弹窗内注入的Controller,存在内存泄漏风险。
可行方案

方案1:直接用Get.bottomSheet实现自定义高度(推荐,无额外内存处理成本)

Get.bottomSheet本身就是对showModalBottomSheet的封装,原生弹窗支持的所有配置参数它都支持,之前无法调整高度是默认配置的问题,只要加两个配置就能自由控制高度:

class MainPage extends StatelessWidget {
  const MainPage({super.key});

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () {
        Get.bottomSheet(
          // 外层套高度容器,自由设置你需要的高度
          SizedBox(
            height: MediaQuery.of(context).size.height * 0.4, // 示例为屏幕高度的40%,也可写固定像素值
            child: const HomePage(),
          ),
          // 关键配置:把弹窗默认背景设为透明,否则默认容器会撑满可用高度
          backgroundColor: Colors.transparent,
          enableDrag: false, // 需要的禁止拖拽配置可正常生效
          isDismissible: true,
          // 其他样式配置和原生弹窗完全一致,比如圆角、阴影等
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
          ),
        );
      },
      child: const Text("唤起底部弹窗"),
    );
  }
}

class GetC extends GetxController {}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final GetC controller = Get.put(GetC());
    return Container(
      decoration: const BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      child: const Text("自定义高度弹窗,Controller自动回收"),
    );
  }
}

这个方案完全走GetX的路由管控逻辑,弹窗关闭时绑定的GetC会被自动回收,不需要写额外的内存处理代码。

方案2:用原生showModalBottomSheet时手动回收Controller

如果有特殊场景必须用原生showModalBottomSheet,只要在弹窗关闭后手动调用GetX的删除方法回收实例即可:

TextButton(
  onPressed: () async {
    // 等待弹窗关闭
    await showModalBottomSheet(
      context: context,
      builder: (context) => const HomePage(),
      enableDrag: false,
    );
    // 弹窗销毁后手动删除对应Controller实例
    Get.delete<GetC>();
  },
  child: const Text("唤起底部弹窗"),
)

注意:如果注入Controller时传了tag参数,删除时也要传入相同的tag才能正确匹配实例:Get.delete<GetC>(tag: "你设置的tag值")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:27:45