美文网首页
Flutter - PopupRoute

Flutter - PopupRoute

作者: 水煮杰尼龟 | 来源:发表于2023-05-25 11:34 被阅读0次

    自定义PopupRoute实现一点弹窗效果,划划水,直接上代码。

    PopupRoute是一个抽象类,首先来extends实现一下

    import 'package:flutter/material.dart';
    
    class WDPopupRoute extends PopupRoute{
    
      // pop动画时间
      Duration? duration;
      Widget child;
      ///背景蒙层颜色
      Color? bgColor;
      WDPopupRoute({
        required this.child,
        this.duration,
        this.bgColor
      });
    
      @override
      // TODO: implement barrierColor
      Color? get barrierColor => (bgColor!=null?bgColor:Colors.black.withOpacity(0.35));
    
      @override
      // TODO: implement barrierDismissible
      bool get barrierDismissible => true;
    
      @override
      // TODO: implement barrierLabel
      String? get barrierLabel => null;
    
      @override
      Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
        // TODO: implement buildPage
        return child;
      }
    
      @override
      // TODO: implement transitionDuration
      Duration get transitionDuration => (duration!=null?duration!:Duration(milliseconds: 330));
    
    }
    

    然后再使用一下·下面是项目中封装了一个插件

    
    import 'package:flutter/material.dart';
    import 'wd_popup_route.dart';
    
    enum WDCustomPopTypes{
      //屏幕居中
      screen_center,
      //点击视图的左上角
      child_lefttop,
      //点击视图的点击位置
      child_tappositon,
    }
    ///与点击视图绑定的pop,可以点哪就从哪弹出视图
    class WDCustomPop extends StatelessWidget {
    
      ///点击视图
      Widget child;
      ///内容视图
      Widget contentChild;
      /// 弹出类型
      WDCustomPopTypes? popType;
      /// 点击内容部分响应事件
      Function? onTapContent;
      /// 除screen_center外,其他弹出类型之后,允许基于指定type的位置给一些偏移
      Offset? offset;
      /// 不管类型,自定义弹出位置
      Offset? customOffset;
      ///点击背景是否close
      bool isTapClose;
    
      WDCustomPop({
        Key? key,
        required this.child,
        required this.contentChild,
        this.popType = WDCustomPopTypes.child_lefttop,
        this.offset = Offset.zero,
        this.customOffset,
        this.onTapContent,
        this.isTapClose = true
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return GestureDetector(onTapDown: (details){
          ///获取点击widget在屏幕中的位置
          final RenderBox button = context.findRenderObject()! as RenderBox;
          final RenderBox overlay = Overlay.of(context)!.context.findRenderObject()! as RenderBox;
          final RelativeRect position = RelativeRect.fromRect(
            Rect.fromPoints(
              button.localToGlobal(Offset.zero, ancestor: overlay),
              button.localToGlobal(Offset.zero, ancestor: overlay),
            ),
            Offset.zero & overlay.size,
          );
    
          Offset  os = Offset.zero;
          if (customOffset == null) {
            switch(popType){
              case WDCustomPopTypes.child_lefttop:
                os = Offset(position.left+offset!.dx, position.top+offset!.dy);
                break;
              case WDCustomPopTypes.child_tappositon:
                os = Offset(details.globalPosition.dx+offset!.dx, details.globalPosition.dy+offset!.dy);
                break;
            }
          }
          Navigator.push(
            context,
            WDPopupRoute(child: Material(
              color: Colors.white.withAlpha(0),
              child: GestureDetector(
                child: Stack(
                  children: [
                    Container(
                      width: MediaQuery.of(context).size.width,
                      height: MediaQuery.of(context).size.height,
                      color: Colors.transparent,
                    ),
                    buildPopContent(context, os)
                  ],
                ),
                onTap: (){
                  if (isTapClose) {
                    Navigator.of(context).pop();
                  }
                  FocusManager.instance.primaryFocus?.unfocus();
                },
              ),
            ),)
          );
        },child: child,);
      }
      /// pop显示的内容
      Widget buildPopContent(BuildContext context, Offset os) {
        if (customOffset != null) {
          return Positioned(
            child: GestureDetector(
                child: contentChild,
                onTap: () {
                  if (onTapContent != null) {
                    Navigator.of(context).pop();
                    onTapContent!();
                  }
                }),
            left: customOffset!.dx,
            top: customOffset!.dy,
          );
        }else{
          return (popType == WDCustomPopTypes.screen_center
              ? Center(
            child: contentChild,
          )
              : Positioned(
            child: GestureDetector(
                child: contentChild,
                onTap: () {
                  if (onTapContent != null) {
                    Navigator.of(context).pop();
                    onTapContent!();
                  }
                }),
            left: os.dx,
            top: os.dy,
          ));
        }
        }
    
    }
    
    

    看看效果呗


    xiaoguo.gif

    相关文章

      网友评论

          本文标题:Flutter - PopupRoute

          本文链接:https://www.haomeiwen.com/subject/agzxedtx.html