我有一个从屏幕底部弹出的子菜单。第三个菜单项是“停用此任务”deactivateThisQuest.tr(),当用户点击它时,它会调用 onsubmit() 函数,该函数有一个带有“取消”和“确定”的弹出对话框,点击“取消”关闭对话框并按预期关闭菜单,点击“确定”将 REST POST 发送回服务器。
我想做的是,当用户在弹出对话框上单击“确定”时,我希望它返回到上一个屏幕。但为了做到这一点,需要关闭对话框,然后关闭我们之前调用的弹出菜单,然后返回到上一个屏幕。
如果我放 3 个“Navigator.pop(context);”在如下所示的一行中,它会按预期转到上一个屏幕,但不会触发 API POST。如果我放 2 个“Navigator.pop(context);”连续,然后对话框和菜单关闭并且 API 触发。如果我放一个“Navigator.pop(context);”在 onRefresh() 之后;当对话框和菜单关闭时,API 会触发,但仍然不会返回到上一个屏幕。
关于如何实现这一目标有什么想法吗?
class QuestMenu extends HookConsumerWidget {
const QuestMenu(
{super.key,
required this.questId,
required this.questName,
required this.privateLink,
required this.onRefresh,
this.token,
required this.isJoined,
required this.isDeactivated});
final int questId;
final String questName;
final String privateLink;
final String? token;
final VoidCallback onRefresh;
final bool isJoined;
final bool isDeactivated;
void show(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (_) => QuestMenu(
questId: questId,
questName: questName,
privateLink: privateLink,
token: token,
onRefresh: onRefresh,
isJoined: isJoined,
isDeactivated: isDeactivated),
useRootNavigator: true,
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final onSubmit = useCallback(
() async {
// Show confirmation dialog
await showDialog<bool>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
insetPadding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 24,
),
title: Text(
'deactivateQuest'.tr(),
style: popupTitle.copyWith(color: Palette.titleColor),
textAlign: TextAlign.center,
),
content: Text(
'sureDeactivate'.tr(),
style: basicText.copyWith(color: Palette.generalText),
textAlign: TextAlign.justify,
),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: OutlineButton(
label: 'Cancel',
onPressed: () {
Navigator.pop(context); // Close dialog
Navigator.pop(context); // Close menu
},
//child: Text('Cancel'),
),
),
gapW8, // Adjust spacing between buttons
Expanded(
child: PrimaryButton(
label: 'OK',
onPressed: () async {
Navigator.pop(context); // Close dialog
Navigator.pop(context); // Close menu
Navigator.pop(context); // Go back to previous screen
await ref
.read(deactivateQuestNotifierProvider.notifier)
.deactivateQuest(questId, token: token);
onRefresh();
//Navigator.pop(context); // Go back to previous screen
},
//child: Text('Confirm'),
),
),
],
),
],
);
},
);
},
[],
);
return SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.all(pdMdHorizontal),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_MenuTile(
label: 'clickView'.tr(),
icon: SvgPicture.asset(Assets.svg.routeFilled),
showChevron: true,
onTap: () {
launchUrl(url);
},
),
gapH16,
_MenuTile(
label: 'shareWithFriend'.tr(),
icon: SvgPicture.asset(Assets.svg.share),
showChevron: true,
onTap: () => Share.share(privateLink),
),
gapH16,
if (isJoined && !isDeactivated)
_MenuTile(
label: 'deactivateThisQuest'.tr(),
icon: SvgPicture.asset(Assets.svg.flasher),
showChevron: true,
onTap: onSubmit,
),
],
),
),
);
}
}
class _MenuTile extends StatelessWidget {
const _MenuTile({
required this.icon,
required this.label,
this.onTap,
this.showChevron = false,
});
final SvgPicture icon;
final String label;
final bool showChevron;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: Row(
children: [
icon,
gapW10,
Text(label, style: buttonText.copyWith(color: Palette.activeGreen)),
if (showChevron) const Spacer(),
if (showChevron) SvgPicture.asset(Assets.svg.chevronNext),
],
),
);
}
}
修改 onPressed:
onPressed: () async {
Navigator.pop(context); // Close dialog
Navigator.pop(context); // Close menu
await Future.delayed(Duration(milliseconds: 100)); // Delay for smooth transition (optional)
Navigator.pop(context); // Go back to previous screen
await ref
.read(deactivateQuestNotifierProvider.notifier)
.deactivateQuest(questId, token: token);
onRefresh();
},
“Future.delayed”在关闭菜单后持续时间较短,以允许在返回上一屏幕之前平滑过渡