Flutter 做一个自适应高度的底部弹窗

553 阅读1分钟

话不多说,直接上代码。

class BottomSheetUtils {
  BottomSheetUtils.showBottomSheet(
    BuildContext context, {
    required Widget child,
    double? height, //固定高度
    double? maxHeight, //最大高度
    double minHeight = 213, //最小高度
    double statusBarHeight = 0, //状态栏高度
    double bottomBarHeight = 0, //底部bar高度
    double appBarHeight = 0, //appbar的高度
    Widget? titleView, // 弹窗顶部标题
    double titleHeight = 50, //弹窗顶部标题高度
  }) {
    _bottomSheet(
      context,
      child: child,
      height: height,
      maxHeight: maxHeight,
      minHeight: minHeight,
      statusBarHeight: statusBarHeight,
      bottomBarHeight: bottomBarHeight,
      appBarHeight: appBarHeight,
      titleView: titleView,
      titleHeight: titleHeight,
    );
  }

  ///自适应高度底部弹窗
  void _bottomSheet(
    BuildContext context, {
    required Widget child,
    double? height, //固定高度
    double? maxHeight, //最大高度
    double minHeight = 213, //最小高度
    double statusBarHeight = 0, //状态栏高度
    double bottomBarHeight = 0, //底部bar高度
    double appBarHeight = 0, //appbar的高度
    Widget? titleView, // 弹窗顶部标题
    double titleHeight = 50, //弹窗顶部标题高度
  }) {
    ///如果maxHeight没有设置值,则高度为默认去除statusBarHeight高度与title高度
    maxHeight ??= Get.height -
        statusBarHeight -
        appBarHeight -
        (titleView == null ? 0 : titleHeight);
    Widget widget;
    if (child is ScrollView) {
      /// 如果height没有设置值,则默认为最大高度
      height ??= maxHeight;
      widget = child;
    } else {
      widget = SingleChildScrollView(
        child: child,
      );
    }
    if (titleView == null) {
      /// 没有title
      widget = Container(
        height: height,
        padding: EdgeInsets.only(bottom: bottomBarHeight),
        decoration: const BoxDecoration(

            ///这里设置了背景色和圆角
            color: Colors.white,
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(8), topRight: Radius.circular(8))),
        constraints: BoxConstraints(maxHeight: maxHeight, minHeight: minHeight),
        child: widget,
      );
    } else {
      /// 有title
      widget = Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Expanded(
              child: Container(
            color: Colors.transparent,
          ).onTap(() {
            /// 这里的onTap是我的Widget做的一个扩展,如下:
            ///     extension WidgetExt on Widget {
            ///        Widget onTap(GestureTapCallback onTap) {
            ///          return GestureDetector(
            ///            onTap: onTap,
            ///            child: this,
            ///          );
            ///        }
            ///      }
            Get.back(); // 点击空白区域关闭dialog,这里我用了Getx框架,可以修改为系统或者其他方式关闭弹框
          })),

          /// 此处为弹窗标题
          titleView,

          /// 以下为弹窗内容
          Container(
            height: height,
            padding: EdgeInsets.only(bottom: bottomBarHeight),
            color: Colors.white,
            constraints: BoxConstraints(
                maxHeight: maxHeight, minHeight: minHeight - titleHeight),
            child: widget,
          ),
        ],
      );
    }
    showModalBottomSheet(
        context: context,
        backgroundColor: Colors.transparent,
        isDismissible: true,
        isScrollControlled: true,
        builder: (context) {
          return widget;
        });
  }
}