Flutter simple pop-up window

High-temperature power cuts, epidemic prevention and control, one wave of unrest, another wave of outbreaks.
It is impossible to learn, and you can only barely maintain your life by fishing at home.

There is an integrated pop-up method in Flutter, roughly like this:

  void showPopup() {
    
    
    showModalBottomSheet(
        context: context,
        shape:
            RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
        builder: (BuildContext context) {
    
    
          return Container(
            color: Colors.amber,
            child: Column(
              children: [
                ElevatedButton(onPressed: () {
    
    }, child: Text("1")),
                ElevatedButton(onPressed: () {
    
    }, child: Text("2")),
              ],
            ),
          );
        });
  }

The effect is roughly as follows:
showModalBottomSheet

It is to use showModalBottomSheet or similar APIs, but there are relatively few customizable parameters. For example, the more important positions are difficult to control and not beautiful.
Of course, components that are not free are hard to look good.

So find a way to customize it.
Customization is also simple, look at the source code of showModalBottomSheet, just follow the gourd painting and change it, most custom APIs can do this.

And the source code of showModalBottomSheet is like this:

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,
}) {
    
    
  assert(context != null);
  assert(builder != null);
  assert(isScrollControlled != null);
  assert(useRootNavigator != null);
  assert(isDismissible != null);
  assert(enableDrag != null);
  assert(debugCheckHasMediaQuery(context));
  assert(debugCheckHasMaterialLocalizations(context));

  final NavigatorState navigator = Navigator.of(context, rootNavigator: useRootNavigator);
  return navigator.push(_ModalBottomSheetRoute<T>(
    builder: builder,
    capturedThemes: InheritedTheme.capture(from: context, to: navigator.context),
    isScrollControlled: isScrollControlled,
    barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
    backgroundColor: backgroundColor,
    elevation: elevation,
    shape: shape,
    clipBehavior: clipBehavior,
    constraints: constraints,
    isDismissible: isDismissible,
    modalBarrierColor: barrierColor,
    enableDrag: enableDrag,
    settings: routeSettings,
    transitionAnimationController: transitionAnimationController,
    anchorPoint: anchorPoint,
  ));
}

It's clear at once, the pop-up window is another page pop-up, so naturally there must be another route:

navigator.push(_ModalBottomSheetRoute);

Next, just copy _ModalBottomSheetRoute.

class PopupFreeWindow extends PopupRoute {
    
    
  ///子组件
  final Widget child;
  ///切换动画时长,必要属性
  final Duration duration;
  ///间隔,用于微调位置
  final EdgeInsets margin;
  ///分布,用于控制大体位置 
  final Alignment alignment;
  ///外围遮罩背景色
  Color? outerBackgroudColor;

  ///子控件具体宽度
  double width;
  ///子控件具体高度
  double height;
  ///宽度比例
  double widthFactor;
  ///高度比例 
  double heightFactor;
  ///是否点击外围收起弹窗
  bool dismissable;

  PopupFreeWindow(
      {
    
    required this.child,
      this.duration = const Duration(milliseconds: 300),
      this.alignment = Alignment.bottomCenter,
      this.margin =
          const EdgeInsets.only(bottom: kBottomNavigationBarHeight * 1.5),
      this.widthFactor = 0.95,
      this.heightFactor = 0.3,
      this.width = 0,
      this.height = 0,
      this.dismissable = true});

  @override
  Color? get barrierColor =>
      outerBackgroudColor ?? Colors.black.withOpacity(0.3);

  @override
  bool get barrierDismissible => dismissable;

  @override
  String? get barrierLabel => null;

  @override
  Duration get transitionDuration => duration;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    
    
    Widget? content;
    if (width > 0 && height >= 0) {
    
    
      content = Container(
        alignment: alignment,
        margin: margin,
        child: Container(
          child: child,
          width: width,
          height: height,
        ),
      );
    } else {
    
    
      content = FractionallySizedBox(
          widthFactor: widthFactor,
          heightFactor: heightFactor,
          child: Container(
            child: child,
            margin: margin,
          ),
          alignment: alignment);
    }
    return FadeTransition(
        opacity: animation,
        child: SafeArea(
          child: content,
        ));
  }

}

Test code:

void showbottom() {
    
    
    final size = MediaQuery.of(context).size;
    final width = size.width;
    final height = size.height;
    print("screen w=$width,h=$height");
    Navigator.of(context).push(PopupFreeWindow(
      // widthFactor: 0.95,
      // heightFactor: 0.4,
      height: 200,
      width: width - 30,
      child: ChatBubble(
        direction: ArrowDirection.bottom,
        arrowWidth: 30,
        arrowHeight: 20,
        conicWeight: 4.5,
        child: GridMenu(),
      ),
    ));
  }

Customize the size of the pop-up window according to the real screen size. The default Alignment is the bottom, which can be adjusted. The default bottom interval is 1.5 times that of the status bar, which can be adjusted. This is written here to combine the ChatBubble in the previous blog. Realize the effect of the bottom floating menu.
In fact, they can all be defined by themselves.
The effect is shown in the figure below.
pushRoute
above.
(Continue to fish~)

Guess you like

Origin blog.csdn.net/ifmylove2011/article/details/126757242