我正在使用带有CupertinoDeliversheet小部件的CupertinoModalPopup来显示一组选项供用户 Select .

我打算显示一个循环加载指示器,然后加上复选标记(勾选), 给用户一种他已经点击了该选项的印象,它是 使用Navingator.pop(上下文)弹出后保存. 首先,我try 使用100毫秒的延迟来实现这一点 future .点击按下后延迟 目前仅使用显示循环加载指示器的控件.但它不起作用.

这是我的代码,可以更好地解释我正在做的事情.仅发布相关代码.

@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;
                    });
                  });
                },

单击任意一个选项后,循环加载指示符(延迟:100毫秒),然后是勾选标记(延迟:50毫秒),以给用户一个成功的印象.目前下面仅配置循环加载指示器.

                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(

// 单击任意一个选项后,循环加载指示符(延迟:100毫秒),然后是勾选标记(延迟:50毫秒),以给用户一个成功的印象.目前下面仅配置循环加载指示器.

                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;
  }      

正在工作的是:

选项和 Select 确实按照指定的以毫秒为单位的延迟工作

什么不是:

"启用"和"禁用"操作最后的循环进度指示器不会出现.修复持续时间延迟的循环进度指示器后,我打算调用复选标记勾选小部件,之后复选标记应该出现并从小部件本身弹出.

如果我能指出如何最好地实现上述目标的正确方向

  1. 加载指示器,延迟100毫秒.
  2. 复选标记勾选在加载指示器位于同一位置后立即出现,并在50毫秒后弹出

编辑于2024年4月29日

根据下面 comments 中从@anqit收到的指导,我确实取得了一些进展.已更新代码以反映更改.

推荐答案

Summary:
The StatefulBuilder widgets may not be required, as the BuildContext may come from your custom widget. The ElevatedButton serves as an example of launching the CupertinoActionSheet, which can be substituted with whatever method you are using. Note that I didn't make use of custom widgets such as KNText. The two parts to your question to my understanding are how to 显示加载, and how to show a checkmark after selection and loading. Note I set the delay for loading to 1000ms, so you can see the loading longer in the example.

Loading Summary
The loading CircularProgressIndicator is shown by roughly following the below steps. ref _showLoading function in the code below.

  1. 呼叫showDialog
  2. showDialog返回CircularProgressIndicator
  3. 运行Future.delayed(在生产中是网络呼叫?)
  4. 呼叫Navigator.pop关闭加载对话框

Checkmark Summary:
复选标记可以以多种方式显示,在这种情况下,我使用Visibility来根据下面代码中名为selectedMap中的值隐藏和显示复选标记.当按下模式中的按钮时(加载完成后),selected中的值会更新.大致过程如下

  1. 按下启用或禁用按钮
  2. 显示加载
  3. 加载完成
  4. 根据按下的按钮更新selected的值
  5. rebuild, because setState was called. When building the checkmarks are shown based on the values in selected.

    Button:
    Button

    Modal:
    Modal

    Loading:
    Loading

    Check changed after loading
    changed after loading

Code:

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 {
                            // 显示加载, 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",
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

100

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,
  };

  // if true 显示加载
  bool loadingFlag = false;

  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 {

                            // update flags and set loading flag, then build
                            setState(
                              () {
                                selected["enabled"] = true;
                                selected["disabled"] = false;
                                loadingFlag = true;
                              },
                            );

                            // wait for delay, change loading flag, then build
                            await Future.delayed(
                              const Duration(
                                milliseconds: 1000,
                              ),
                              () {
                                setState(
                                  () {
                                    loadingFlag = false;
                                  },
                                );
                              },
                            );
                          },
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              const Text(
                                "Enabled",
                              ),
                              Visibility(
                                visible: selected["enabled"]!,
                                // check loading flag to determine if should 显示加载 or check
                                child: loadingFlag
                                    ? const CircularProgressIndicator()
                                    : const Icon(
                                        Icons.check,
                                      ),
                              ),
                            ],
                          ),
                        ),
                        CupertinoActionSheetAction(
                          onPressed: ({
                            int index = 0,
                          }) async {
                            // opposite enable disable
                            setState(
                              () {
                                selected["enabled"] = false;
                                selected["disabled"] = true;
                                loadingFlag = true;
                              },
                            );

                            await Future.delayed(
                              const Duration(
                                milliseconds: 1000,
                              ),
                              () {
                                setState(
                                  () {
                                    loadingFlag = false;
                                  },
                                );
                              },
                            );
                          },
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              const Text(
                                "Disabled",
                              ),
                              Visibility(
                                visible: selected["disabled"]!,
                                child: loadingFlag
                                    ? const CircularProgressIndicator()
                                    : const Icon(
                                        Icons.check,
                                      ),
                              ),
                            ],
                          ),
                        ),
                      ],
                      cancelButton: CupertinoActionSheetAction(
                        isDefaultAction: true,
                        onPressed: () {
                          Navigator.pop(
                            context,
                          );
                        },
                        child: const Text(
                          "Cancel",
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

Flutter相关问答推荐

ListView内的ListView正在一次构建所有项目

如何让GridView.builder用另外两个小部件来占据屏幕的剩余部分

Riverpod状态管理-在调用请求时更新用户界面

为什么要在值列表中两次放入空安全性

我不能在Fighting中裁剪图片输入错误,否则应用程序会崩溃

如何将请求字段正确添加到DART多部分请求

Flutter中不使用Container是否可以做margin

ScaffoldMessenger 在等待键下方不起作用

点击后,将按钮的 colored颜色 禁用/更改一段时间

Firestore 使用 Flutter 以奇怪的格式保存数据

如何解决需要一个标识符,但得到的是:.try 在:之前插入一个标识符.dart 错误

flutter 在文本字段中更改部分文本选定 colored颜色

Flutter snapShot.hasData 为假但响应有数据

在 CircleAvatar 中放置芯片

Flutter 如何使用 ClipPath 编辑容器的顶部?

无法将参数类型Future Function(String?)分配给参数类型void Function(NotificationResponse)?

无法列出 com.facebook.android:facebook-login -Facebook 登录问题的版本

Flutter Firestore 数据库排序最近 24 小时内最喜欢的文档

try 为两个下拉值添加共享首选项,但在 Flutter 上显示错误断言失败:?

如何从我的Flutter 项目中删除错误?