CupertinoActionSheetAction onPressed 触发加载指示器,后跟带有延迟的复选标记

问题描述 投票:0回答:1

我使用带有 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;
  }      

什么在起作用:

选项和选择确实会按指定的毫秒延迟工作

什么不:

“启用”和“禁用”操作末尾的循环进度指示器不会出现。在修复了具有延迟持续时间的圆形进度指示器后,我打算调用一个复选标记刻度小部件,之后复选标记应该出现并从小部件本身弹出。

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

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

编辑截至 2024 年 4 月 29 日

根据下面评论中@anqit 提供的指导,我确实取得了一些进展。已更新代码以反映更改。

flutter dart flutter-cupertino cupertino-widgets
1个回答
0
投票

总结:
可能不需要

StatefulBuilder
小部件,因为
BuildContext
可能来自您的自定义小部件。
ElevatedButton
作为启动
CupertinoActionSheet
的示例,可以用您正在使用的任何方法替换。请注意,我没有使用自定义小部件,例如
KNText
。据我了解,您的问题的两个部分是如何显示加载,以及如何在选择和加载后显示复选标记。注意我将加载延迟设置为 1000 毫秒,因此您可以在示例中看到加载时间更长。

加载摘要
加载
CircularProgressIndicator
大致按照以下步骤显示。参考下面代码中的
_showLoading
函数。

  1. 致电
    showDialog
  2. showDialog
    返回
    CircularProgressIndicator
  3. 运行
    Future.delayed
    (在生产中进行网络调用?)
  4. 调用
    Navigator.pop
    关闭加载对话框

复选标记摘要:
复选标记可以通过多种方式显示,在本例中,我根据下面代码中名为 Visibility

Map
 中的值,使用 
selected
 来隐藏和显示复选标记。当按下模态中的按钮时(加载完成后),
selected
中的值会更新。大致流程如下

  1. 启用或禁用按下的按钮
  2. 显示加载中
  3. 加载完成
  4. 根据按下的按钮更新
    selected
    中的值
  5. 重建,因为调用了
    setState
    。构建时,根据
    selected
    中的值显示复选标记。

    按钮:
    Button

    模态:
    Modal

    加载中:
    Loading

    加载后检查已更改
    changed after loading

代码:

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",
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ),
      ),
    ),
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.