0
点赞
收藏
分享

微信扫一扫

showModalBottomSheet自适应高度

路西法阁下 2021-10-04 阅读 168

背景:

showModalBottomSheet是系统提供的底部弹窗,但是正常情况高度是固定的。内容少的时候底部弹窗下面空一片不太好看。需要根据显示内容的高度来调整弹窗的高度。

showModalBottomSheet的isScrollControlled属性,设置为true,弹窗会覆盖整个手机。设置为false,弹窗大概是整个屏幕的9/16高。
ConstrainedBox 这是一个可以限制子控件高度的控件。

思路:

由于我的弹窗里面主要是放了一个listview,所以我会在代码里面打印出list的的每一个item的高度。然后算出真个listview的高度。把isScrollControlled设置为true,在用ConstrainedBox限制listview的高度。这样listview多高,弹窗就是多高。

///项目通用的底部弹窗
void showBottomDialog(BuildContext context, List<String> list,Function onItem) async {
  if ((list != null) && !list.contains('取消')) {
    list.add('取消');
  }

  await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (BuildContext context) {
        //56
        return ConstrainedBox(
          constraints: BoxConstraints(maxHeight: getHeight(context, list)),
          child: ListView.separated(
            itemCount: list == null ? 0 : list.length,
            separatorBuilder: (context, index) {
              return Divider(
                height: 0,
              );
            },
            itemBuilder: (context, index) {
              return ListTile(
                title: GestureDetector(
                  child: Container(
                    color: Colors.transparent,
                    width: double.infinity,
                    height: 45,
                    alignment: Alignment.center,
                    child: Text(
                      list[index] ?? "",
                      style: textStyle_black,
                    ),
                  ),
                  onTap: () {
                    if (index == list.length - 1) {
                      Navigator.of(context).pop();
                    }else{
                      onItem(index);
                    }
                  },
                ),
              );
            },
          ),
        );
      });
}
double getHeight(BuildContext context, List<String> list) {
  if (56.0 * (list?.length) > MediaQuery.of(context).size.height * 0.8) {
    return MediaQuery.of(context).size.height * 0.8;
  }
  return 56.0 * (list?.length);
}

当有滚动布局的时候,需要设置isScrollControlled为true
下面是源码中对高度的限制,不设置只能是屏幕的9/16的高度。

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    return BoxConstraints(
      minWidth: constraints.maxWidth,
      maxWidth: constraints.maxWidth,
      minHeight: 0.0,
      maxHeight: isScrollControlled
        ? constraints.maxHeight
        : constraints.maxHeight * 9.0 / 16.0,
    );
  }

少量列表


大量列表最大直到屏幕的80%


二、重新实现

上面是初学时候写的,现在根据简友的评论重新写了下,之所以没有删除上面的,是因为上面还是有些知识点的。实用直接拿下面的代码。


///项目通用的底部弹窗
void showBottomDialog(
    BuildContext context, List<String?> list, Function onItem) async {

  double maxShowHeight = MediaQuery.of(context).size.height * 0.8;
  double itemHeight = 56.h;
  Widget listView() {
    return ListView.separated(
      shrinkWrap: true,
      itemCount: list.length,
      separatorBuilder: (context, index) {
        return Divider(
          height: 1,
          color: fillColor,
        );
      },
      itemBuilder: (context, index) {
        return GestureDetector(
          child: Container(
            color: Colors.white,
            width: double.infinity,
            height: 56.h,
            alignment: Alignment.center,
            child: Text(
              list[index] ?? "",
              style: styleBlack_16,
            ),
          ),
          onTap: () {
            onItem(index);
            Navigator.of(context).pop();
          },
        );
      },
    );
  }

  Widget cancelWidget() {
    return GestureDetector(
        onTap: () => Navigator.of(context).pop(),
        child: Container(
          color: Colors.white,
          margin: EdgeInsets.only(top: 8.h),
          height: 54.h,
          width: 1.sw,
          alignment: Alignment.center,
          child: Text(
            "取消",
            style: styleBlack_16,
          ),
        ));
  }

  await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      builder: (BuildContext context) {


        return ConstrainedBox(
          constraints: BoxConstraints(
              maxHeight: maxShowHeight),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              list.length >= maxShowHeight / itemHeight   ? Expanded(child: listView()) : listView(),
              cancelWidget(),
            ],
          ),
        );
      });
}


举报

相关推荐

0 条评论