Как я могу разделить одно нажатие и двойное нажатие кнопки возврата во флаттере?
Я пытаюсь сделать функцию выхода из приложения, когда дважды нажимаю кнопку возврата в CupertinoTabbar
.
Хотя я применил различные функции, такие как DoubleBackToCloseApp
плагин или WillPopScope
, всякий раз, когда я нажимаю кнопку "Назад", появлялось сообщение о выходе.
Следовательно, я хочу создать код, работающий следующим образом:
- просто нажмите кнопку назад один раз, вернитесь перед страницами
- нажмите дважды в течение нескольких секунд, выйдите из приложения.
моя панель вкладок следующая:
class TabPage extends StatefulWidget {
final FirebaseUser currentUser;
TabPage(this.currentUser);
@override
_TabPageState createState() => _TabPageState();
}
class _TabPageState extends State<TabPage> {
int _selectedIndex = 0;
static const snackBarDuration = Duration(seconds: 1);
DateTime backbuttonpressedTime;
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
final GlobalKey<NavigatorState> homeTabNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> groupTabNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> feedTabNavKey = GlobalKey<NavigatorState>();
final GlobalKey<NavigatorState> userTabNavKey = GlobalKey<NavigatorState>();
@override
void initState() {
_firebaseMessaging.onTokenRefresh.listen(sendTokenToServer);
_firebaseMessaging.getToken();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return !await currentNavigatorKey().currentState.maybePop();
},
child: Scaffold(
body: WillPopScope(
onWillPop: _onWillPop,
child: CupertinoTabScaffold(
tabBar: CupertinoTabBar(
activeColor: Theme
.of(context)
.colorScheme
.mainColor,
inactiveColor: Theme
.of(context)
.colorScheme
.greyColor,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home)),
BottomNavigationBarItem(
icon: Icon(Icons.group)),
BottomNavigationBarItem(
icon: Icon(Icons.favorite_border)),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle)),
],
onTap: (index) {
// back home only if not switching tab
if (_selectedIndex == index) {
switch (index) {
case 0:
homeTabNavKey.currentState.popUntil((r) => r.isFirst);
break;
case 1:
groupTabNavKey.currentState.popUntil((r) => r.isFirst);
break;
case 2:
feedTabNavKey.currentState.popUntil((r) => r.isFirst);
break;
case 3:
userTabNavKey.currentState.popUntil((r) => r.isFirst);
break;
}
}
_selectedIndex = index;
},
),
tabBuilder: (BuildContext context, int index) {
switch (index) {
case 0:
return CupertinoTabView(
navigatorKey: homeTabNavKey,
builder: (BuildContext context) => HomePage(),
);
break;
case 1:
return CupertinoTabView(
navigatorKey: groupTabNavKey,
builder: (BuildContext context) => GroupPage(),
);
break;
case 2:
return CupertinoTabView(
navigatorKey: feedTabNavKey,
builder: (BuildContext context) => FeedPage(widget.currentUser),
);
break;
case 3:
return CupertinoTabView(
navigatorKey: userTabNavKey,
builder: (BuildContext context) =>
UserPage(widget.currentUser?.uid),
);
break;
}
return null;
},
),
),
),
);
}
void sendTokenToServer(String fcmToken) {
print('Token: $fcmToken');
Firestore.instance.collection('pushtokens')
.document(widget.currentUser.uid)
.setData({
'pushToken': fcmToken
});
}
GlobalKey<NavigatorState> currentNavigatorKey() {
switch (_selectedIndex) {
case 0:
return homeTabNavKey;
break;
case 1:
return groupTabNavKey;
break;
case 2:
return feedTabNavKey;
break;
case 3:
return userTabNavKey;
break;
}
return null;
}
//
Future<bool> _onWillPop() async {
DateTime currentTime = DateTime.now();
//Statement 1 Or statement2
bool backButton = backbuttonpressedTime == null ||
currentTime.difference(backbuttonpressedTime) > Duration(seconds: 2);
if (backButton) {
backbuttonpressedTime = currentTime;
Fluttertoast.showToast(
msg: "Double Click to exit app",
backgroundColor: Colors.black,
textColor: Colors.white);
return false;
}
return true;
}
}
Спасибо!
Я наконец решил эту проблему. Выложу обновленный код!
int backbuttonpressedTime = 0;
Future<bool> _onWillPop() async {
var currentTime = DateTime.now().millisecondsSinceEpoch;
if(!currentNavigatorKey().currentState.canPop()) {
if (currentTime-backbuttonpressedTime < Duration(seconds: 2).inMilliseconds) {
return SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}else{
Fluttertoast.showToast(
msg: "Double Click to exit app",
backgroundColor: Colors.black,
timeInSecForIos: 1,
textColor: Colors.white);
backbuttonpressedTime = currentTime;
return false;
}
}else{
return true;
}
}
Я только модифицировал _onWillPop()
часть. Спасибо!
2 ответа
Вот мое решение https://pub.dev/packages/flutter_close_app
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return FlutterCloseAppPage(
onCloseFailed: () {
// Condition does not match: the first press or the second press interval is more than 2 seconds, display a prompt message
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Press again to exit '),
));
},
child: Scaffold(
appBar: AppBar(),
body: ...
),
);
}
}
В простых случаях, когда вам нужно перехватить кнопку возврата Android, вы обычно добавляете WillPopScope в дерево виджетов. Однако при разработке виджетов с отслеживанием состояния, которые взаимодействуют с кнопкой "Назад", удобнее использовать BackButtonInterceptor. Взглянуть: