flutter- 全局悬浮可拖动的Widget

提记:
 爱情
 一段感情能给你带来多少痛苦,就曾给你带来过多大快乐
 既想放弃,又想纠缠,内心经历了多少痛苦和挣扎
 用一转身离开,用一辈子忘记

需求背景:

那天,产品经理说“我在微信朋友圈里点了别人分享出来的歌曲链接 听了会歌 那歌简直了 好听 退到聊天界面 出现了个悬浮的歌曲图标 那我们能不能做类似的 在所有页面都会存在这样一个悬浮图标 这个图标目前要有打客服电话功能”。
我一心想,这人真会搞事 哈哈。行 满足他

OverlayState是什么?

事实上有一个Overlay的widget,它的createState方法获取的就是OverlayState对象.
Overlay可以认为是一个UI上面的蒙版/浮空层,使用起来类似Stack;

有这几个API 熟悉一下
OverlayState.insert(OverlayEntry) //添加
OverlayEntry.remove() //移除
在pubspec.yaml添加url_launcher依赖
dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^5.5.0
先定义个Application类
import 'package:flutter/cupertino.dart';
class Application {
  ///应用全局 ke
   static GlobalKey<NavigatorState>  globalKey;
   static OverlayEntry overlayEntry;
}
主入口程序如下
void main() {
  GlobalKey<NavigatorState> globalKey = new  GlobalKey<NavigatorState>();
  Application.globalKey = globalKey;
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
    ///注意 一定要navigatorKey 才能在所有界面上显示
      navigatorKey: Application.globalKey,
      home: MyHomePage(),
    );
  }
}
MyHomePage类
class MyHomePage extends StatefulWidget {
  @override
  _SecondState createState() => _SecondState();
}

class _MyHomePageState extends State<Second> {
  OverlayEntry overlayEntry;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    WidgetsBinding.instance.addPostFrameCallback((_) {
      ///WidgetsBinding.instance.addPostFrameCallback 这个作用是界面绘制完成的监听回调  必须在绘制完成后添加OverlayEntry
      ///MediaQuery.of(context).size.width  屏幕宽度
      ///MediaQuery.of(context).size.height 屏幕高度
       addOverlayEntry(MediaQuery.of(context).size.width - 80, MediaQuery.of(context).size.height - 80);
    });


  }

  Future addOverlayEntry(double left, double top) async {
    Application.overlayEntry?.remove();
    overlayEntry = OverlayEntry(
        builder: (BuildContext context) => Positioned(
          top:  top,
          left: left,
          child: GestureDetector(
              onTap: () async{
                ///在这里实现拨打客服电话功能
                const url = 'tel:17601290637';
                   if (await canLaunch(url)) {
                     await launch(url);
                   } else {
                     throw 'Could not launch $url';
                   }
              },
              child: Draggable(
                onDragEnd: (DraggableDetails details) {
                  ///拖动结束
                  addOverlayEntry(details.offset.dx, details.offset.dy);
                },
                ///feedback是拖动时跟随手指滑动的Widget。
                feedback: Icon(Icons.add_call, color: Colors.red,),
                  ///child是静止时显示的Widget,
                  child: Icon(Icons.add_call, color: Colors.red,))
          ),
        )
    );
    /// 赋值  方便移除
    Application.overlayEntry = overlayEntry;
    Application.globalKey.currentState.overlay.insert(overlayEntry);
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(),
    );
  }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。