Flutter全局悬浮按钮
生活随笔
收集整理的這篇文章主要介紹了
Flutter全局悬浮按钮
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
方法一
Offset _offset = Offset.zero;Scaffold(body: Stack(children: [_pageList[_currentIndex],Positioned(left: _offset.dx,top: _offset.dy,child: GestureDetector(onPanUpdate: (d) =>setState(() => _offset += Offset(d.delta.dx, d.delta.dy)),child: FloatingActionButton(onPressed: () {},backgroundColor: Colors.orange,child: Icon(Icons.add),),),),],),方法二
WidgetsBinding.instance.addPostFrameCallback((_) => _insertOverlay(context)); void _insertOverlay(BuildContext context) {return Overlay.of(context).insert(OverlayEntry(builder: (context) {final size = MediaQuery.of(context).size;print(size.width);return Positioned(width: 56,height: 56,top: size.height - 72,left: size.width - 72,child: Material(color: Colors.transparent,child: GestureDetector(onTap: () => print('ON TAP OVERLAY!'),child: Container(decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.redAccent),),),),);}),);}方法三
1.場景 現在需要做一個Test按鈕,懸浮在所有頁面之上,并且可以拖拽。
2.思路 1)懸浮按鈕可以使用flutter提供的Overlay + OverlayEntry 組合實現
2)拖拽功能可以使用GestureDetector手勢按鈕或者Draggable實現(PS:我做了一版Draggable實現的,但是發現它會有原本的widget浮在原地,顯然不是我要的效果)
3)點擊的時候我是讓它彈出一個底部彈框,這里你們可以自由發揮,本篇文章不做多余贅述
PubScaffold(child: MaterialApp(theme: CustomTheme.lightTheme,darkTheme: CustomTheme.darkTheme,themeMode: currentTheme.currentTheme,home: Scaffold(body: Stack(children: [_pageList[_currentIndex],// Positioned(// left: _offset.dx,// top: _offset.dy,// child: GestureDetector(// onPanUpdate: (d) =>// setState(() => _offset += Offset(d.delta.dx, d.delta.dy)),// child: FloatingActionButton(// onPressed: () {},// backgroundColor: Colors.orange,// child: Icon(Icons.add),// ),// ),// ),],),bottomNavigationBar: CurvedNavigationBar(// key: _bottomNavigationKey,index: 0,height: 60.0,items: <Widget>[Icon(Icons.home, size: 30),Icon(Icons.list, size: 30),Icon(Icons.compare_arrows, size: 30),// Icon(Icons.call_split, size: 30),],color: Colors.white,buttonBackgroundColor: Colors.white,backgroundColor: Colors.blueAccent,animationCurve: Curves.easeInOut,animationDuration: Duration(milliseconds: 600),onTap: (index) {setState(() {_currentIndex = index;});},// letIndexChange: (index) => true,),),),);這里的PubScaffold就是我封裝的一個懸浮按鈕組件,把它包裹在MaterialApp外面,就可以實現懸浮在所有的組件之上的一個按鈕啦(當然也可以不是按鈕,具體樣式可以自己定義)。下面我們來看一下PubScaffold中的代碼吧~
import 'dart:math';import 'package:flutter/material.dart';class PubScaffold extends StatefulWidget {final Widget child;PubScaffold({this.child});@override_PubScaffoldState createState() => _PubScaffoldState(); }class _PubScaffoldState extends State<PubScaffold> {bool draggable = false;//靜止狀態下的offsetOffset idleOffset = Offset(0, 0);//本次移動的offsetOffset moveOffset = Offset(0, 0);//最后一次down事件的offsetOffset lastStartOffset = Offset(0, 0);int count = 0;final List<String> testWidgetList = ['測試1','測試2',];testAppFun(e) {// TODO: 你的代碼邏輯}// 顯示一個底部彈窗,這里是一個測試列表showTestList() {showModalBottomSheet(context: context,enableDrag: false,shape: RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(20.0),topRight: Radius.circular(20.0),),),builder: (BuildContext context) {return ListView(children: testWidgetList.map((e) => Container(decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Color(0xFFe3e3e3)),),),child: ListTile(onTap: () => testAppFun(e),title: Text(e),),),).toList(),);},);}@overrideWidget build(BuildContext context) {return LayoutBuilder(builder: (context, constraints) {// 顯示懸浮按鈕WidgetsBinding.instance.addPostFrameCallback((_) => _insertOverlay(context));return widget.child;},);}// 懸浮按鈕,可以拖拽(可自定義樣式)void _insertOverlay(BuildContext context) {return Overlay.of(context).insert(OverlayEntry(builder: (context) {final size = MediaQuery.of(context).size;print(size.width);return Positioned(top: draggable ? moveOffset.dy : size.height - 102,left: draggable ? moveOffset.dx : size.width - 72,child: GestureDetector(// 移動開始onPanStart: (DragStartDetails details) {setState(() {lastStartOffset = details.globalPosition;draggable = true;});if (count <= 1) {count++;}},// 移動中onPanUpdate: (DragUpdateDetails details) {setState(() {moveOffset =details.globalPosition - lastStartOffset + idleOffset;if (count > 1) {moveOffset = Offset(max(0, moveOffset.dx), moveOffset.dy);} else {moveOffset = Offset(max(0, moveOffset.dx + (size.width - 72)),moveOffset.dy + (size.height - 102));}});},// 移動結束onPanEnd: (DragEndDetails detail) {setState(() {idleOffset = moveOffset * 1;});},child: TestContainer(onPress: () => showTestList(),),),);}),);} }// 懸浮按鈕的樣式 class TestContainer extends StatelessWidget {final Function onPress;TestContainer({this.onPress});@overrideWidget build(BuildContext context) {return Material(color: Colors.transparent,child: GestureDetector(onTap: onPress,child: Container(width: 56,height: 56,alignment: Alignment.center,decoration: BoxDecoration(shape: BoxShape.circle,color: Colors.green[600],),child: Text("Test",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold,),),),),);} }1.全局懸浮按鈕
這里我們用的是flutter自帶的material庫中的Overlay組件,具體使用方法如下:
void _insertOverlay(BuildContext context) {return Overlay.of(context).insert(OverlayEntry(builder: (context) {final size = MediaQuery.of(context).size;print(size.width);return Positioned(top: draggable ? moveOffset.dy : size.height - 102,left: draggable ? moveOffset.dx : size.width - 72,child: GestureDetector(// 移動開始onPanStart: (DragStartDetails details) {setState(() {lastStartOffset = details.globalPosition;draggable = true;});if (count <= 1) {count++;}},// 移動中onPanUpdate: (DragUpdateDetails details) {setState(() {moveOffset =details.globalPosition - lastStartOffset + idleOffset;if (count > 1) {moveOffset = Offset(max(0, moveOffset.dx), moveOffset.dy);} else {moveOffset = Offset(max(0, moveOffset.dx + (size.width - 72)),moveOffset.dy + (size.height - 102));}});},// 移動結束onPanEnd: (DragEndDetails detail) {setState(() {idleOffset = moveOffset * 1;});},child: TestContainer(onPress: () => showTestList(),),),);}),);}總結
以上是生活随笔為你收集整理的Flutter全局悬浮按钮的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开发中总结的dart相关的技巧
- 下一篇: 信息系统项目管理师采购管理