Dart 如何使用flatter编写按下双返回按钮退出应用程序
我是个新手,我看到很多android应用程序在双击后退按钮时都可以退出Dart 如何使用flatter编写按下双返回按钮退出应用程序,dart,flutter,Dart,Flutter,我是个新手,我看到很多android应用程序在双击后退按钮时都可以退出 第一次按“后退”按钮时,应用程序将显示一个祝酒词“再次按可退出应用程序”。 第二次按下后,应用程序退出。 当然,两次按压之间的时间不能太长 如何在flatter中执行此操作?这是我的代码示例(我使用了“flattertoast”来显示toast消息,您可以使用snackbar或alert或其他任何工具) DateTime currentBackPressTime; @凌驾 小部件构建(构建上下文){ 返回脚手架( ... b
第一次按“后退”按钮时,应用程序将显示一个祝酒词“再次按可退出应用程序”。 第二次按下后,应用程序退出。 当然,两次按压之间的时间不能太长
如何在flatter中执行此操作?这是我的代码示例(我使用了“flattertoast”来显示toast消息,您可以使用snackbar或alert或其他任何工具)
DateTime currentBackPressTime;
@凌驾
小部件构建(构建上下文){
返回脚手架(
...
body:WillPopScope(子项:getBody(),onWillPop:onWillPop),
);
}
未来的onWillPop(){
DateTime now=DateTime.now();
如果(currentBackPressTime==null | |
现在.差异(currentBackPressTime)>持续时间(秒:2)){
currentBackPressTime=现在;
flattertoast.showtoos(消息:退出警告);
返回Future.value(false);
}
返回未来值(true);
}
您可以试试这个软件包
在包装所有小部件的Scaffold
内,放置DoubleBackToCloseApp
并传递一个SnackBar:
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
家:脚手架(
正文:DoubleBackToCloseApp(
孩子:家(),
snackBar:const snackBar(
内容:文本(“再次点击返回以离开”),
),
),
),
);
}
}
旧答案
您还可以选择包含SnackBar
的解决方案。这并不像你的答案那么简单,但它更优雅,而且你不会依赖于图书馆
class\u FooState扩展状态{
静态常数snackBarDuration=持续时间(秒:3);
最终蛇杆=蛇杆(
内容:文本(“再次按后退以离开”),
持续时间:snackBarDuration,
);
DateTime BackButton按时间;
@凌驾
小部件构建(构建上下文){
返回脚手架(
//BuildContext必须来自脚手架的一个子项。
车身:建造商(
生成器:(上下文){
返回式示波器(
onWillPop:()=>handleWillPop(上下文),
孩子:文本(“将孩子放在这里”),
);
},
),
);
}
未来handleWillPop(BuildContext上下文)异步{
final now=DateTime.now();
最后一个BackButton按钮未按下NackBar按钮已关闭=
backButtonPressTime==null||
现在。差异(backButtonPressTime)>snackBarDuration;
如果(BackButton未按下NackBar已关闭){
backButtonPressTime=现在;
脚手架.of(上下文).showSnackBar(snackBar);
返回false;
}
返回true;
}
}
第一次按后退按钮时,应用程序显示一个警报对话框“按是退出应用程序,按否无法退出应用程序”。
这是我的代码示例(我使用了“AlertDialog”)
@覆盖
小部件构建(构建上下文){
返回新的Willposcope(
onWillPop:_onBackPressed,
子级:DefaultTabController(
初始索引:\ u选择索引,
长度:选择。长度,
孩子:脚手架(
appBar:appBar(
),
),
),
);
}
未来_onBackPressed(){
返回显示对话框(
上下文:上下文,
生成器:(上下文){
返回警报对话框(
标题:文本(“你确定吗?”),
内容:文本(“是否要退出应用程序”),
行动:[
扁平按钮(
child:Text('No'),
已按下:(){
Navigator.of(context.pop)(false);
},
),
扁平按钮(
子项:文本('Yes'),
已按下:(){
Navigator.of(context.pop)(true);
},
)
],
);
},
)??假;
}
这是我的答案。我使用AlertDialog()实现了这一点
@override
Widget build(BuildContext context) {
return new WillPopScope(
onWillPop: _onBackPressed,
child: Scaffold(
appBar: AppBar(),
body: Container(),
),
);
}
Future<bool> _onBackPressed() {
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Confirm'),
content: Text('Do you want to exit the App'),
actions: <Widget>[
FlatButton(
child: Text('No'),
onPressed: () {
Navigator.of(context).pop(false); //Will not exit the App
},
),
FlatButton(
child: Text('Yes'),
onPressed: () {
Navigator.of(context).pop(true); //Will exit the App
},
)
],
);
},
) ?? false;
}
@覆盖
小部件构建(构建上下文){
返回新的Willposcope(
onWillPop:_onBackPressed,
孩子:脚手架(
appBar:appBar(),
主体:容器(),
),
);
}
未来_onBackPressed(){
返回显示对话框(
上下文:上下文,
生成器:(上下文){
返回警报对话框(
标题:文本(“确认”),
内容:文本(“是否要退出应用程序”),
行动:[
扁平按钮(
child:Text('No'),
已按下:(){
Navigator.of(context.pop(false);//将不会退出应用程序
},
),
扁平按钮(
子项:文本('Yes'),
已按下:(){
Navigator.of(context.pop(true);//将退出应用程序
},
)
],
);
},
)??假;
}
只需使用double\u back\u关闭应用程序库即可
将double_back_添加到pubspec.yaml文件中依赖项下的_close_应用程序中
dependencies:
double_back_to_close_app: ^1.2.0
这里是示例代码
import 'package:double_back_to_close_app/double_back_to_close_app.dart';
import 'package:flutter/material.dart';
void main() => runApp(Example());
class Example extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: DoubleBackToCloseApp(
snackBar: const SnackBar(
content: Text('Tap back again to leave'),
),
child: Center(
child: OutlineButton(
child: const Text('Tap to simulate back'),
// ignore: invalid_use_of_protected_member
onPressed: WidgetsBinding.instance.handlePopRoute,
),
),
),
),
);
}
}
只需将身体内容移动到“DoubleBackToCloseApp”的子项如果你想要一个snackbar,你应该提供一个脚手架键,因为它与脚手架相关,所以这个键应该能够在它的脚手架父项之外调用snackbar
以下是一个解决方案:
class Home extends StatelessWidget {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async{
DateTime initTime = DateTime.now();
popped +=1;
if(popped>=2) return true;
await _scaffoldKey.currentState.showSnackBar(
SnackBar(
behavior: SnackBarBehavior.floating,
content: Text('Tap one more time to exit.',textAlign: TextAlign.center,),
duration: Duration(seconds: 2),
)).closed;
// if timer is > 2 seconds reset popped counter
if(DateTime.now().difference(initTime)>=Duration(seconds: 2)) {
popped = 0;
}
return false;
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(title : Text("Demo")),
body: Text("body")
);
)
}
class Home扩展了无状态小部件{
最终GlobalKey _scaffoldKey=新的GlobalKey();
@凌驾
小部件构建(构建上下文){
返回式示波器(
onWillPop:()异步{
DateTime initTime=DateTime.now();
弹出+=1;
如果(弹出>=2)返回true;
等待_scaffoldKey.currentState.showSnackBar(
小吃条(
行为:SnackBarBehavior.floating,
内容:Text('再点击一次退出',textAlign:textAlign.center,),
import 'package:double_back_to_close_app/double_back_to_close_app.dart';
import 'package:flutter/material.dart';
void main() => runApp(Example());
class Example extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: DoubleBackToCloseApp(
snackBar: const SnackBar(
content: Text('Tap back again to leave'),
),
child: Center(
child: OutlineButton(
child: const Text('Tap to simulate back'),
// ignore: invalid_use_of_protected_member
onPressed: WidgetsBinding.instance.handlePopRoute,
),
),
),
),
);
}
}
class Home extends StatelessWidget {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async{
DateTime initTime = DateTime.now();
popped +=1;
if(popped>=2) return true;
await _scaffoldKey.currentState.showSnackBar(
SnackBar(
behavior: SnackBarBehavior.floating,
content: Text('Tap one more time to exit.',textAlign: TextAlign.center,),
duration: Duration(seconds: 2),
)).closed;
// if timer is > 2 seconds reset popped counter
if(DateTime.now().difference(initTime)>=Duration(seconds: 2)) {
popped = 0;
}
return false;
},
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(title : Text("Demo")),
body: Text("body")
);
)
}
DateTime currentBackPressTime;
/// init counter of clicks
int pressCount=1;
Future<bool> onWillPop() async {
DateTime now = DateTime.now();
/// here I check if number of clicks equal 3
if(pressCount!=3){
///should be assigned at the first click.
if(pressCount ==1 )
currentBackPressTime = now;
pressCount+=1;
return Future.value(false);
}else{
if (currentBackPressTime == null ||
now.difference(currentBackPressTime) > Duration(seconds: 2)) {
currentBackPressTime = now;
pressCount=0;
return Future.value(false);
}
}
return Future.value(true);
}
class DoubleBackToCloseWidget extends StatefulWidget {
final Widget child; // Make Sure this child has a Scaffold widget as parent.
const DoubleBackToCloseWidget({
@required this.child,
});
@override
_DoubleBackToCloseWidgetState createState() =>
_DoubleBackToCloseWidgetState();
}
class _DoubleBackToCloseWidgetState extends State<DoubleBackToCloseWidget> {
int _lastTimeBackButtonWasTapped;
static const exitTimeInMillis = 2000;
bool get _isAndroid => Theme.of(context).platform == TargetPlatform.android;
@override
Widget build(BuildContext context) {
if (_isAndroid) {
return WillPopScope(
onWillPop: _handleWillPop,
child: widget.child,
);
} else {
return widget.child;
}
}
Future<bool> _handleWillPop() async {
final _currentTime = DateTime.now().millisecondsSinceEpoch;
if (_lastTimeBackButtonWasTapped != null &&
(_currentTime - _lastTimeBackButtonWasTapped) < exitTimeInMillis) {
Scaffold.of(context).removeCurrentSnackBar();
return true;
} else {
_lastTimeBackButtonWasTapped = DateTime.now().millisecondsSinceEpoch;
Scaffold.of(context).removeCurrentSnackBar();
Scaffold.of(context).showSnackBar(
_getExitSnackBar(context),
);
return false;
}
}
SnackBar _getExitSnackBar(
BuildContext context,
) {
return SnackBar(
content: Text(
'Press BACK again to exit!',
color: Colors.white,
),
backgroundColor: Colors.red,
duration: const Duration(
seconds: 2,
),
behavior: SnackBarBehavior.floating,
);
}
}
class Dashboard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: DoubleBackToCloseWidget(
child: Container(
child: Column(
children: [
const Text('Hello there'),
const Text('Hello there again'),
],
),
),
),
),
);
}
}