【交互 widget】 Flutter BottomSheet

1,451 阅读2分钟

BottomSheet 是一个 Material Design StatefulWidget。我们很少直接使用他,而是通过 showBottomSheetshowModalBottomSheet 使用他。

showBottomSheet 用法

PersistentBottomSheetController<T> showBottomSheet<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  Color? backgroundColor,
  double? elevation,
  ShapeBorder? shape,
  Clip? clipBehavior,
  BoxConstraints? constraints,
  bool? enableDrag,
  AnimationController? transitionAnimationController,
})

backgroundColor 是 bottomSheet 的背景色,默认是不透明的,要想透明可以设置为 Colors.transparent。elevation 基本上看不到什么效果,因为 elevation 大多在底下,如果不想用矩形可以指定 shape。比如指定为圆形 shape: CircleBorder(),也可以设置为圆角,shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),圆角可能用的更多些。

showModalBottomSheet(
       context: context,
       shape: RoundedRectangleBorder(
           borderRadius:
               BorderRadius.vertical(top: Radius.circular(30))),
       builder: ((context) {
         return Container(
           decoration: BoxDecoration(
               border: Border.all(width: 3, color: Colors.green)),
           height: 100,
         );
       }));

虽然 shape 为 圆角,但 child 仍然可以在 shape 之外绘制,好像 shape 没有设置一样。需要自己注意,在远离边缘的地方绘制 child,用 ClipRRect 也可以。

enableDrag 默认为 true,可以拖动改变 BottomSheet 的高度。一直往下拖可以让 BottomSheet 消失。如果 enableDrag 是 false 就无法拖动了。

一般情况下用默认值就可以了。showBottomSheet 默认没有 padding。

showBottomSheet(
         context: context,
         builder: ((context) {
           return Container(
             height: 300,
           );
}));

这种由 showBottomSheet 方法弹出的 sheet 是 persistent sheet。是和 modal 相对而言的。persistent sheet 允许用户和 sheet 之外的 UI 交互,modal 不允许用户和 sheet 之外的 UI 交互。

showModalBottomSheet 用法

Future<T?> showModalBottomSheet<T>({
  required BuildContext context,
  required WidgetBuilder builder,
  Color? backgroundColor,
  double? elevation,
  ShapeBorder? shape,
  Clip? clipBehavior,
  BoxConstraints? constraints,
  Color? barrierColor,
  bool isScrollControlled = false,
  bool useRootNavigator = false,
  bool isDismissible = true,
  bool enableDrag = true,
  RouteSettings? routeSettings,
  AnimationController? transitionAnimationController,
  Offset? anchorPoint,
}) 

与 showBottomSheet 相比,多了 barrierColor,是蒙层的颜色。不是不让用户与 sheet 之外的 UI 交互吗?办法就是蒙起来。isDismissible 为 true ,点蒙层可以关闭 sheet。anchorPoint 分屏用的,暂时用不到,分屏的场景暂时还太少了。RouteSettings 用于路由监听,因为 bottomSheet 也是一个路由。isScrollControlled 如果设置为true,当 child 为 ListView,GridView 等滚动 widget 的时候,可以全屏。

使用的时候也是直接用默认值就好了。

showModalBottomSheet(
      context: context,
      builder: ((context) {
        return Container(
          height: 300,
        );
      }));