我使用带有 CupertinoActionSheet 小部件的 CupertinoModalPopup 来显示一组选项供用户选择。
我打算显示一个圆形加载指示器,后跟一个复选标记(勾号) 给用户留下他已经点击了该选项的印象 使用 Navingator.pop(context) 弹出后保存。 首先,我尝试使用延迟 100 毫秒来执行此操作 点击 onPressed 后 Future.delayed 目前仅使用显示圆形加载指示器的小部件。但它不起作用。
这是我的代码,可以更好地解释我在做什么。仅发布相关代码。
@override
Widget build(BuildContext context) {
return CupertinoActionSheet(
title: KNText(
style: TextStyle(color: primaryTextColor),
'Video sound settings',
),
message: KNText(
style: TextStyle(color: primaryTextColor),
'Please choose from an option below :',
),
actions: <Widget>[
Container(
color: primaryColor,
child: CupertinoActionSheetAction(
onPressed: ({int index = 0}) async {
await Future.delayed(const Duration(milliseconds: 100), () {
setState(() {
VideosSoundSetting newType =
allVideosSoundSettings[index];
widget.onTypeChanged(newType);
_setEnabledInProgress(true);
Navigator.pop(context);
});
setState(() {
_enabledInProgress = false;
});
});
},
// A circular loading indicator(delay : 100 milliseconds) followed by a checkmark tick(delay:50 milliseconds) will appear for a brief time after clicking on either option to give the user an impression that its a success. Currently , only circular loading indicator is configured below.
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 153.0),
child: KNText(
style: TextStyle(color: primaryTextColor),
'Enabled',
),
),
_enabledInProgress
? const CircularProgressIndicator()
: Container()
],
),
)),
Container(
color: primaryColor,
child: CupertinoActionSheetAction(
// A circular loading indicator(delay : 100 milliseconds) followed by a checkmark tick(delay:50 milliseconds) will appear for a brief time after clicking on either option to give the user an impression that its a success. Currently , only circular loading indicator is configured below.
onPressed: ({int index = 0}) async {
await Future.delayed(const Duration(milliseconds: 100), () {
setState(() {
VideosSoundSetting newType =
allVideosSoundSettings[index];
widget.onTypeChanged(newType);
_setEnabledInProgress(true);
Navigator.pop(context);
});
setState(() {
_enabledInProgress = false;
});
});
},
child: Row(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 150.0),
child: KNText(
style: TextStyle(color: primaryTextColor),
'Disabled',
),
),
_enabledInProgress
? const CircularProgressIndicator()
: Container()
],
),
)),
],
cancelButton: Container(
color: primaryColor,
child: CupertinoActionSheetAction(
isDefaultAction: true,
onPressed: () {
Navigator.pop(context);
},
child: const Row(children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 155.0),
child: KNText(
style: TextStyle(
color: Color.fromRGBO(255, 0, 0, 1.0),
fontWeight: FontWeight.w700),
'Cancel',
),
),
]),
),
));
}
void _setEnabledInProgress(bool enabledInProgress) {
_enabledInProgress = enabledInProgress;
}
什么在起作用:
选项和选择确实会按指定的毫秒延迟工作
什么不:
“启用”和“禁用”操作末尾的循环进度指示器不会出现。在修复了具有延迟持续时间的圆形进度指示器后,我打算调用一个复选标记刻度小部件,之后复选标记应该出现并从小部件本身弹出。
如果我能指出如何最好地实现上述目标的正确方向
编辑截至 2024 年 4 月 29 日
根据下面评论中@anqit 提供的指导,我确实取得了一些进展。已更新代码以反映更改。
StatefulBuilder
小部件,因为 BuildContext
可能来自您的自定义小部件。 ElevatedButton
作为启动 CupertinoActionSheet
的示例,可以用您正在使用的任何方法替换。请注意,我没有使用自定义小部件,例如 KNText
。据我了解,您的问题的两个部分是如何显示加载,以及如何在选择和加载后显示复选标记。注意我将加载延迟设置为 1000 毫秒,因此您可以在示例中看到加载时间更长。
CircularProgressIndicator
大致按照以下步骤显示。参考下面代码中的 _showLoading
函数。
showDialog
showDialog
返回 CircularProgressIndicator
Future.delayed
(在生产中进行网络调用?)Navigator.pop
关闭加载对话框复选标记摘要:
复选标记可以通过多种方式显示,在本例中,我根据下面代码中名为 Visibility
的
Map
中的值,使用
selected
来隐藏和显示复选标记。当按下模态中的按钮时(加载完成后),selected
中的值会更新。大致流程如下
selected
中的值setState
。构建时,根据 selected
中的值显示复选标记。
代码:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
// used to indicate which option is selected
Map<String, bool> selected = {
"enabled": true,
"disabled": false,
};
// shows the loading indicator
Future<void> _showLoading({
required BuildContext context,
}) async {
// show dialog overlay with just a progress indicator
showDialog(
barrierDismissible: false,
context: context,
builder: (context) => const Center(
child: CircularProgressIndicator(
color: Colors.red,
),
),
);
// run delay - assume swapping for some kind of network call
// on delay done pop loading dialog
await Future.delayed(
const Duration(
milliseconds: 1000,
),
() {
Navigator.pop(
context,
);
},
);
}
runApp(
MaterialApp(
home: Scaffold(
body: StatefulBuilder(
builder: (context, setState) => Center(
// button to trigger modal
child: ElevatedButton(
child: const Text(
"Click to test",
),
onPressed: () => showCupertinoModalPopup(
context: context,
builder: (BuildContext modalContext) {
/*
Rough example begins
*/
return StatefulBuilder(
builder: (context, setState) => CupertinoActionSheet(
title: const Text(
"Video sound settings",
),
message: const Text(
"Please choose from an option below :",
),
actions: [
CupertinoActionSheetAction(
onPressed: ({
int index = 0,
}) async {
// show loading, and wait till function done
await _showLoading(
context: context,
);
// tell flutter to build, check will be shown based on values set on next build
setState(
() {
selected["enabled"] = true;
selected["disabled"] = false;
},
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Enabled",
),
Visibility(
visible: selected["enabled"]!,
child: const Icon(
Icons.check,
),
),
],
),
),
CupertinoActionSheetAction(
onPressed: ({
int index = 0,
}) async {
await _showLoading(
context: context,
);
// opposite values
setState(
() {
selected["enabled"] = false;
selected["disabled"] = true;
},
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Disabled",
),
Visibility(
visible: selected["disabled"]!,
child: const Icon(
Icons.check,
),
),
],
),
),
],
cancelButton: CupertinoActionSheetAction(
isDefaultAction: true,
onPressed: () {
Navigator.pop(
context,
);
},
child: const Text(
"Cancel",
),
),
),
);
},
),
),
),
),
),
),
);
}