提记:
爱情
一段感情能给你带来多少痛苦,就曾给你带来过多大快乐
既想放弃,又想纠缠,内心经历了多少痛苦和挣扎
用一转身离开,用一辈子忘记
需求背景:
那天,产品经理说“我在微信朋友圈里点了别人分享出来的歌曲链接 听了会歌 那歌简直了 好听 退到聊天界面 出现了个悬浮的歌曲图标 那我们能不能做类似的 在所有页面都会存在这样一个悬浮图标 这个图标目前要有打客服电话功能”。
我一心想,这人真会搞事 哈哈。行 满足他
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(),
);
}
}