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

Flutter中如何让showModalBottomSheet实现响应式适配?

解决方案

要实现WebView状态变化时自动调整BottomSheet高度,核心是监听WebView加载状态、获取网页实际高度并动态更新BottomSheet容器高度,具体实现如下:

1. 改用StatefulWidget管理BottomSheet状态

把原BottomSheet组件改为带状态的组件,用于动态更新高度:

class DynamicHeightBottomSheet extends StatefulWidget {
  const DynamicHeightBottomSheet({super.key});

  @override
  State<DynamicHeightBottomSheet> createState() => _DynamicHeightBottomSheetState();
}

class _DynamicHeightBottomSheetState extends State<DynamicHeightBottomSheet> {
  InAppWebViewController? _webViewController;
  double _bottomSheetHeight = MediaQuery.of(context).size.height - (kToolbarHeight * 2); // 初始高度
  final double _minHeight = 200; // 最小高度限制

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      height: _bottomSheetHeight,
      decoration: BoxDecoration(
        color: lmWhite,
        borderRadius: BorderRadius.circular(20.r),
      ),
      clipBehavior: Clip.hardEdge,
      child: Stack(
        children: [
          InAppWebView(
            initialUrlRequest: URLRequest(url: Uri.parse("你的网页地址")),
            onWebViewCreated: (controller) {
              _webViewController = controller;
            },
            onLoadStop: (controller, url) async {
              // 网页加载完成后获取实际滚动高度
              final scrollHeight = await controller.getScrollHeight();
              if (scrollHeight != null) {
                setState(() {
                  // 计算适配高度:不超过屏幕可用高度,同时不低于最小高度
                  final screenAvailableHeight = MediaQuery.of(context).size.height - kToolbarHeight - 20; // 预留顶部间距
                  _bottomSheetHeight = scrollHeight > screenAvailableHeight 
                      ? screenAvailableHeight 
                      : scrollHeight > _minHeight 
                          ? scrollHeight 
                          : _minHeight;
                });
              }
            },
            // 可选:监听网页滚动/内容变化,实时更新高度(按需启用,频繁调用可能影响性能)
            onScrollChanged: (controller, x, y) async {
              // final scrollHeight = await controller.getScrollHeight();
              // if (scrollHeight != null) {
              //   setState(() {
              //     _bottomSheetHeight = scrollHeight;
              //   });
              // }
            },
          ),
          // 你的Opacity组件示例
          Opacity(opacity: 0.5, child: Container(color: Colors.black.withOpacity(0.1))),
        ],
      ),
    );
  }
}

2. 调整showModalBottomSheet参数

确保isScrollControlled保持为true,让BottomSheet支持动态高度调整:

showModalBottomSheet(
  enableDrag: false,
  isDismissible: false,
  isScrollControlled: true,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.only(
      topRight: Radius.circular(20.r),
      topLeft: Radius.circular(20.r),
    ),
  ),
  context: context,
  builder: (context) => const DynamicHeightBottomSheet(),
);

关键细节

  • 核心逻辑:通过InAppWebViewController.getScrollHeight()获取网页实际高度,这是实现动态调整的基础。
  • 边界控制:设置最小高度避免BottomSheet过矮,同时限制最大高度不超过屏幕可用空间,防止内容溢出。
  • 性能考量:优先在onLoadStop事件中更新高度,如需实时响应内容变化再启用onScrollChanged监听,减少不必要的状态更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:25:19