フラッターのシンプルなポップアップ ウィンドウ

高温の停電、伝染病の予防と抑制、不安の波、アウトブレイクの波。
学ぶことは不可能であり、家で釣りをすることはかろうじて生活を維持することしかできません。

Flutter には、大まかに次のようなポップアップ メソッドが統合されています。

  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")),
              ],
            ),
          );
        });
  }

効果はおおよそ次のとおりです。
showModalBottomSheet

showModalBottomSheetなどの APIを使用することですが、カスタマイズできるパラメータが比較的少なく、たとえば重要な位置ほど制御が難しく、美しくありません。
もちろん、無料ではないコンポーネントは見栄えがよくありません。

そこで、カスタマイズする方法を見つけます。
カスタマイズも簡単です。showModalBottomSheet のソース コードを見て、ひょうたんの絵をたどって変更するだけです。ほとんどのカスタム API でこれを行うことができます。

また、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,
}) {
    
    
  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,
  ));
}

すぐに明らかです。ポップアップ ウィンドウは別のページ ポップアップなので、当然、別のルートが必要です。

navigator.push(_ModalBottomSheetRoute);

次に、_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,
        ));
  }

}

テストコード:

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(),
      ),
    ));
  }

実際の画面サイズに応じて、ポップアップ ウィンドウのサイズをカスタマイズします. デフォルトの配置は調整可能な下部です. デフォルトの下部の間隔は、調整可能なステータス バーの 1.5 倍です. これはここに書かれています前回のブログのChatBubbleを組み合わせて、一番下のフローティングメニューの効果を実感。
実際、それらはすべて自分で定義できます。
その効果を下図に示します。
プッシュルート
その上。
(釣り続けて~)

おすすめ

転載: blog.csdn.net/ifmylove2011/article/details/126757242