flutter- 全局懸浮可拖動的Widget

提記:
 愛情
 一段感情能給你帶來多少痛苦,就曾給你帶來過多大快樂
 既想放棄,又想糾纏,內(nèi)心經(jīng)歷了多少痛苦和掙扎
 用一轉(zhuǎn)身離開,用一輩子忘記

需求背景:

那天,產(chǎn)品經(jīng)理說“我在微信朋友圈里點(diǎn)了別人分享出來的歌曲鏈接 聽了會歌 那歌簡直了 好聽 退到聊天界面 出現(xiàn)了個(gè)懸浮的歌曲圖標(biāo) 那我們能不能做類似的 在所有頁面都會存在這樣一個(gè)懸浮圖標(biāo) 這個(gè)圖標(biāo)目前要有打客服電話功能”。
我一心想,這人真會搞事 哈哈。行 滿足他

OverlayState是什么?

事實(shí)上有一個(gè)Overlay的widget,它的createState方法獲取的就是OverlayState對象.
Overlay可以認(rèn)為是一個(gè)UI上面的蒙版/浮空層,使用起來類似Stack;

有這幾個(gè)API 熟悉一下
OverlayState.insert(OverlayEntry) //添加
OverlayEntry.remove() //移除
在pubspec.yaml添加url_launcher依賴
dependencies:
  flutter:
    sdk: flutter
  url_launcher: ^5.5.0
先定義個(gè)Application類
import 'package:flutter/cupertino.dart';
class Application {
  ///應(yīng)用全局 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 這個(gè)作用是界面繪制完成的監(jiān)聽回調(diào)  必須在繪制完成后添加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{
                ///在這里實(shí)現(xiàn)撥打客服電話功能
                const url = 'tel:17601290637';
                   if (await canLaunch(url)) {
                     await launch(url);
                   } else {
                     throw 'Could not launch $url';
                   }
              },
              child: Draggable(
                onDragEnd: (DraggableDetails details) {
                  ///拖動結(jié)束
                  addOverlayEntry(details.offset.dx, details.offset.dy);
                },
                ///feedback是拖動時(shí)跟隨手指滑動的Widget。
                feedback: Icon(Icons.add_call, color: Colors.red,),
                  ///child是靜止時(shí)顯示的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(),
    );
  }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容