美文网首页
flutter全局浮动按钮

flutter全局浮动按钮

作者: neobuger | 来源:发表于2023-05-09 16:55 被阅读0次

    flutter全局浮动按钮

    1.添加

    
    import 'package:flutter/material.dart';
    import 'first.dart';
    import 'Application.dart';
    
    void main() {
      Application.initKey();
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
          // routes: RouteGenerator.routes,
          navigatorKey: Application.globalKey,
    
          debugShowCheckedModeBanner: false,
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
    
      OverlayEntry? overlayEntry;
    
    
    
      @override
      void initState() {
        super.initState();
    
        WidgetsBinding.instance.addPostFrameCallback((_) {
          ///WidgetsBinding.instance.addPostFrameCallback 这个作用是界面绘制完成的监听回调  必须在绘制完成后添加OverlayEntry
          ///MediaQuery.of(context).size.width  屏幕宽度
          ///MediaQuery.of(context).size.height 屏幕高度
          print('开始添加');
          // addOverlayEntry(MediaQuery.of(context).size.width - 180, MediaQuery.of(context).size.height - 180);
          // addOverlayEntry( 180, 180);
          Application.addOverlayEntry(10, 200);
          Application.callBlock = () {
            Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => FirstVC(),
                ));
          };
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
    
            title: Text(widget.title),
          ),
          body: Column(
            children: [
              
            ],
          ),
    
        );
      }
    }
    
    

    2.创建

    import 'package:flutter/material.dart';
    import 'package:flutter/cupertino.dart';
    typedef CallBlock = void Function();
    class Application {
      ///应用全局 key
      static GlobalKey<NavigatorState>  ?globalKey ;//= GlobalKey<NavigatorState>();
      static OverlayEntry ?overlayEntry;
    
      static bool hideChild = false;
      static CallBlock ? callBlock;
    
      static double dx = 10;
      static double dy = 200;
    
      static bool isChange = false;
      static changeChildShow (){
        hideChild = false;
        Future.delayed(Duration(milliseconds: 200)).then((e) {
          Application.addOverlayEntry(dx, dy);
        });
      }
    
    
      static initKey(){
        GlobalKey<NavigatorState> globalKey = new  GlobalKey<NavigatorState>();
        Application.globalKey = globalKey;
      }
    
    
      static getStopColor(){
        if (isChange) {
          return Colors.transparent;
        }
        return Colors.black;
      }
    
      static Future addOverlayEntry(double left, double top) async {
        Application.overlayEntry?.remove();
        overlayEntry = OverlayEntry(
            builder: (BuildContext context) => Positioned(
              top:  top,
              left: left,
              child: GestureDetector(
                  onTap: () async{
    
                    print('点击');
                    if (callBlock != null) {
                      callBlock!();
    
                      hideChild = true;
                    }
    
                  },
                  child: Offstage(
                    offstage: hideChild,
                    child: Draggable(
                        onDragUpdate: (DragUpdateDetails details){
                          isChange = true;
                        },
                        onDragEnd: (DraggableDetails details) {
                          isChange = false;
                          ///拖动结束
                          dx = details.offset.dx;
                          dy = details.offset.dy;
    
                          if (dx < 10) {
                            dx = 10;
                          }
                          else if (dx >= MediaQuery.of(context).size.width - 40) {
                            dx = MediaQuery.of(context).size.width-40;
                          }
                          else if (dx <= MediaQuery.of(context).size.width/2) {
                            dx = 10;
                          }
                          else if (dx > MediaQuery.of(context).size.width /2) {
                            dx = MediaQuery.of(context).size.width-40;
                          }
                          if (dy < 100) {
                            dy = 100;
                          }
                          if (dy > MediaQuery.of(context).size.height - 140) {
                            dy = MediaQuery.of(context).size.height - 140;
                          }
                          addOverlayEntry( dx,  dy);
    
                        },
                        ///feedback是拖动时跟随手指滑动的Widget。
                        feedback: Container(width: 30,height: 30,color: Colors.black,),
                        ///child是静止时显示的Widget,
                        child: Container(width: 30,height: 30,color: getStopColor(),)),
                  )
              ),
            )
        );
        /// 赋值  方便移除
        Application.overlayEntry = overlayEntry;
        if (Application.globalKey!.currentState != null) {
          Application.globalKey!.currentState!.overlay!.insert(overlayEntry!);
        }
      }
    
    
    }
    

    3.知识点

    3.1 key [1]

    key:在Flutter中,Key是不能重复使用的,所以Key一般用来做唯一标识。组件在更新的时候,其状态的保存主要是通过判断组件的类型或者key值是否一致。
    GlobalKey:

    局部键(LocalKey):ValueKey、ObjectKey、UniqueKey

    全局键(GlobalKey):GlobalObjectKey
    GlobalKey是全局唯一的键,一般而言,GlobalKey有如下几种用途:
    用途1:获取配置、状态以及组件位置尺寸等信息
    (1)_globalKey.currentWidget:获取当前组件的配置信息(存在widget树中)
    (2)_globalKey.currentState:获取当前组件的状态信息(存在Element树中)
    (3)_globalKey.currentContext:获取当前组件的大小以及位置信息。

    用途2:实现控件的局部刷新
    将需要单独刷新的widget从复杂的布局中抽离出去,然后通过传GlobalKey引用,这样就可以通过GlobalKey实现跨组件的刷新了。
    navigatorKey:
    navigatorKey 相当于 Navigator.of(context) ,如果应用程序想实现无 context 跳转,那么可以通过设置该key, 通过 navigatorKey.currentState.overlay.context 获取全局context。

    3.2 overlay[2]

    Overlay是一个可以管理的堆栈。我们可以通过将一个Widget插入这个堆栈中,这样就可以让此Widget浮在其他的Widget之上,从而实现悬浮窗效果。我们可以通过OverlayEntry对象的配置来管理Overlay的层级关系。

    OverlayEntry 是一个定义Widget


    参考


    1. Flutter中的Key详解

    2. 说说Flutter中的Overlay

    相关文章

      网友评论

          本文标题:flutter全局浮动按钮

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