Flutter笔记:Widgets Easier组件库(10)快速处理承若型对话

news2025/1/12 19:02:45
Flutter笔记
使用Widgets Easier组件库快速处理承若型对话

- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSitehttp://thispage.tech/
Email: 291148484@163.com.
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/138342874
HuaWei:https://bbs.huaweicloud.com/blogs/426781

组件库地址

  • Pub.Dev:https://pub.dev/packages/widgets_easier
  • GitHub:https://github.com/jacklee1995/widgets_easier
  • 国内访问(更新延迟):https://pub-web.flutter-io.cn/packages/widgets_easier

【介绍】:使用Widgets Easier组件库快速处理承若型弹窗。

flutter-ljc


上一节:《 Widgets Easier组件库(9)使用弹窗 | 下一节:《 Widgets Easier组件库(11)使用卡片


1. 概述

1.1 关于Widgets Easier

本库是一个 Flutter 组件库,旨在提供用于Flutter开发的组件,使得开发者能够更简单地构建出更丰富地界面效果。项目地址为:

  • https://github.com/jacklee1995/widgets_easier

  • https://pub.dev/packages/widgets_easier

1.2 模块安装

在你的Flutter项目中,运行下面的命令:

flutter pub add widgets_easier

即可安装最新版本的 Widgets Easier 库。

2. 什么是承若型对话

2.1 基本概念

承若型对话是一套带有异步性质的弹窗机制。这种弹窗机制能够广泛运用于处理登录验证等具有未来性质。

一个 Future 对象在其生命周期中有两种状态:

  1. 未完成(Uncompleted):

当 Future 被创建时,它处于未完成状态。这意味着异步操作尚未完成,结果还不可用。

  1. 完成(Completed):

异步操作完成后,Future 进入完成状态。这个状态有两种可能的结果:

  • 成功(Fulfilled): 异步操作成功完成,Future 获得了一个值。

  • 失败(Rejected): 异步操作因错误而未能成功完成,Future 获得了一个错误。

与之对应的,在承若型对话中注重的时过程,也即是更关注 UncompletedCompleted 的过度状态和状态结果。这就是说,在一组承若型对话中至少有三个对话单元(Dialog),分别是

  1. 加载中;
  2. 加载完成;
    1. 加载成功
    2. 加载失败

3. 案例:用户登录

以用户登录为例,承若型对话可以被设计为以下三个阶段的对话单元:

  1. 加载中(Loading):

当用户提交登录信息(如用户名和密码)后,应用会显示一个加载中的对话框或提示。这个阶段对应于 Future 的 未完成(Uncompleted) 状态,表示登录的异步操作正在进行中,结果尚未确定。

  1. 加载完成(Completion):

这个阶段对应于 Future 的 完成(Completed) 状态,根据操作的结果,可以进一步分为两个子阶段:

  1. 加载成功(Success):

如果登录验证成功,应用会显示一个成功的提示对话框或者直接跳转到应用的主界面。这表示异步操作成功完成,用户被成功验证。

  1. 加载失败(Failure):

如果登录失败(例如,因为提供了错误的凭证或服务器无响应),应用会显示一个错误提示对话框。这个对话框通常会提供错误信息,并可能允许用户重试或进行其他恢复操作。

这种承若型对话机制不仅提高了用户体验,通过明确显示每个阶段的状态,还帮助用户理解应用的当前状态和可能的下一步操作。例如,在登录过程中:

用户输入凭证并点击“登录”按钮。

系统立即响应,显示一个模态加载中对话框,通知用户“正在验证,请稍候…”。

根据异步验证结果,加载中对话框会被替换为:

成功对话框,显示“登录成功!欢迎回来。”然后可能会自动关闭对话框并导航到主界面。

失败对话框,显示“登录失败,请检查您的用户名和密码后重试。”并提供重试或找回密码的选项。

通过这种方式,承若型对话为异步操作提供了清晰和直观的用户反馈,增强了交互的连贯性和用户的信任感。

4. 使用Widgets Easier库实现

使用 Widgets Easier库实现一个承若型对话单元特别简单你只需要准备好你的验证UI和校验函数,对话的事情可以完全交给 Widgets Easier库来实现。

4.1 使用FutureDialogs类

FutureDialogs 类用于处理承若型弹窗,通过静态方法 FutureDialogs.show 调用弹窗。

FutureDialogs.show 方法需要配置一个异步函数futureCallback和两个 Dialog 模板,一个是 SuccessDialog、另外一个是FailureDialog,如果有需要也可以指定第三个Dialog模板 LoadingDialog。其中:

  • 异步函数futureCallback表示一个具有两个结果的未来事件,它可能成功或者失败;
    • futureCallback的结果遵循一定规范,返回结果的类型为Future<Map<String, dynamic>>
    • 这个Map中,包含statusdata两个字段;
    • status的类型为bool,表示成功或者失败;
    • data表示是一个字符串,表示成功或者失败时相关消息。
  • futureCallback还未实现(fulfill)的过程中,展示的是 LoadingDialog
  • 如果futureCallback实现(fulfill)后的而己过为成功,则展示 SuccessDialog
  • 反之则展示FailureDialog

4.2 构建一个SuccessDialog

现在我们构建一个

import 'package:flutter/material.dart';

import 'package:gap/gap.dart';

class SuccessDialog extends StatelessWidget {
  final String data;
  const SuccessDialog(
    this.data, {
    super.key,
  });

  
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.center,
      child: Material(
        color: Colors.transparent,
        child: Container(
          width: 200,
          height: 200,
          margin: const EdgeInsets.all(26),
          padding: const EdgeInsets.all(26),
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.6),
            borderRadius: BorderRadius.circular(16),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(
                Icons.check,
                color: Colors.green,
                size: 60,
              ),
              const Gap(20),
              Text(data, style: const TextStyle(color: Colors.white)),
            ],
          ),
        ),
      ),
    );
  }
}

4.3 构建一个FailureDialog

import 'package:flutter/material.dart';
import 'package:gap/gap.dart';

class FailureDialog extends StatelessWidget {
  final String data;
  const FailureDialog(
    this.data, {
    super.key,
  });

  
  Widget build(BuildContext context) {
    return Align(
      alignment: Alignment.center,
      child: Material(
        color: Colors.transparent,
        child: Container(
          width: 230,
          height: 200,
          margin: const EdgeInsets.all(16),
          padding: const EdgeInsets.all(16),
          decoration: BoxDecoration(
            color: Colors.black.withOpacity(0.6),
            borderRadius: BorderRadius.circular(16),
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              const Icon(
                Icons.close,
                color: Colors.red,
                size: 60,
              ),
              const Gap(20),
              Text(data,
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  )),
            ],
          ),
        ),
      ),
    );
  }
}

4.4 登录页面

import 'package:example/login/dialogs/failure_dialog.dart';
import 'package:flutter/material.dart';
import 'package:widgets_easier/widgets_easier.dart';

import 'dialogs/success_dialog.dart';
import 'login_controller.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage> {
  final TextEditingController usernameController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();
  final LoginController loginManager = LoginController();

  void handleLogin(BuildContext context) {
    // 从文本控制器获取用户名和密码
    final String username = usernameController.text;
    final String password = passwordController.text;

    // 显示一个异步操作的对话框,这个对话框将在 simulateLogin 方法的 Future 完成后关闭
    FutureDialogs.show<String>(
      context: context,
      futureCallback: () => loginManager.simulateLogin(username, password),
      buildSuccessDialog: (data) {
        return SuccessDialog(data);
      },
      buildFailureDialog: (data) {
        return FailureDialog(data);
      },
    ).then((result) {
      // 检查从 simulateLogin 返回的结果
      if (result != null && result['status'] == true) {
        // 如果登录成功,导航到主页
        Navigator.pushReplacementNamed(context, '/login-success');
      }
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('FutureDialogs 示例')),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            TextField(
              controller: usernameController,
              decoration: const InputDecoration(
                labelText: '输入你的账号',
                border: OutlineInputBorder(),
                prefixIcon: Icon(Icons.account_circle),
              ),
            ),
            const SizedBox(height: 10),
            TextField(
              controller: passwordController,
              decoration: const InputDecoration(
                labelText: '输入你的密码',
                border: OutlineInputBorder(),
                prefixIcon: Icon(Icons.lock),
              ),
              obscureText: true,
            ),
            const SizedBox(height: 20),
            SemanticButton(
              text: '登录',
              type: SemanticEnum.primary,
              onTap: () => handleLogin(context),
              radius: 40,
              isOutlined: true,
            )
          ],
        ),
      ),
    );
  }
}

其中:

FutureDialogs.show<String>(
      context: context,
      futureCallback: () => loginManager.simulateLogin(username, password),
      buildSuccessDialog: (data) {
        return SuccessDialog(data);
      },
      buildFailureDialog: (data) {
        return FailureDialog(data);
      },
    ).then((result) {
      // 检查从 simulateLogin 返回的结果
      if (result != null && result['status'] == true) {
        // 如果登录成功,导航到主页
        Navigator.pushReplacementNamed(context, '/login-success');
      }
    });

可以我们在完成完成之后还可以链式执行一些操作。这种设计非常有必要,以此例子为例,在登录成功之后我们跳转到了登录成功页面。其中这里then的参数result也是futureCallback返回的值。另一方面,如果有需要也可以在这里继续下一个弹窗。

4.5 异步函数

import 'dart:async';

class LoginController {
  Future<Map<String, dynamic>> simulateLogin(
    String username,
    String password,
  ) async {
    // 一般对于空密码等情况可以在客户端验证,以减少API请求
    if (username.isEmpty || password.isEmpty) {
      return {
        'status': false,
        'data': '账户名或密码不能为空',
      };
    }
    // 模拟请求API返回结果,有可能成功也有可能失败
    else if (username == 'jclee95' && password == '123456') {
      await Future.delayed(const Duration(seconds: 1));
      return {'status': true, 'data': '登录成功'};
    } else {
      await Future.delayed(const Duration(seconds: 1));
      return {'status': false, 'data': '账户名或密码错误'};
    }
  }
}

在这段代码中,simulateLogin是一个模拟异步登录的函数。
如果登录成功,则返回:

{'status': true, 'data': '登录成功'}

如果登录失败则返回:

{'status': false, 'data': '账户名或密码错误'}

4.6 登录成功页面

import 'package:flutter/material.dart';

class LoginSuccessView extends StatelessWidget {
  const LoginSuccessView({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('登录成功'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Icon(
              Icons.check_circle_outline,
              size: 100,
              color: Colors.green,
            ),
            const Padding(
              padding: EdgeInsets.all(8.0),
              child: Text(
                '您已成功登录!',
                style: TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                  color: Colors.black,
                ),
              ),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.pushReplacementNamed(context, '/home');
              },
              child: const Text('回到主页'),
            ),
          ],
        ),
      ),
    );
  }
}

4.7 效果展示

用户名密码为空:
在这里插入图片描述

输入错误的密码:

在这里插入图片描述
密码认证成功

在这里插入图片描述

5. 弹窗动画

5.1 FutureDialogs.zoomIn方法

在之前的内容中,我介绍了FutureDialogs.show的基本用法,这个方法没有动进入画效果。另外有一个 FutureDialogs.zoomIn方法拥有完全一样的接口,但是拥有从小到大的动画效果,看起来就像这样:

在这里插入图片描述

5.2 自定义动画

如果有需要,你可以使用 FutureDialogs.showFutureDialog 静态方法自定义动画。该方法有一个transitionBuilder参数接受一个RouteTransitionsBuilder,可以用于指定动画。例如之前弹窗部分代码修改为:

FutureDialogs.showFutureDialog(
  context: context,
  transitionBuilder: (context, animation, secondaryAnimation, child) {
    return AnimateStyles.rollIn(animation, child);
  },
  futureCallback: () => loginManager.simulateLogin(username, password),
  buildSuccessDialog: (data) {
    return SuccessDialog(data);
  },
  buildFailureDialog: (data) {
    return FailureDialog(data);
  },
).then((result) {
  // 检查从 simulateLogin 返回的结果
  if (result != null && result['status'] == true) {
    // 如果登录成功,导航到主页
    Navigator.pushReplacementNamed(context, '/login-success');
  }
});

注:这里使用的AnimateStyles.rollIn动画需要单独安装:

flutter pub add flutter_easy_animations

效果看起来是这样的:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1641611.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ApiHug 官方站点

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplacehttps://…

[数据结构]——非递归排序总结——笔试爱考

具体代码实现在gitee&#xff1a;登录 - Gitee.com 目录 具体代码实现在gitee&#xff1a;登录 - Gitee.com 1.非递归实现的快速排序算法。 第一步 首先要创建一个栈 第二步紧接着进行入栈&#xff0c;出栈&#xff0c;弹出栈顶元素&#xff0c;获取栈顶元素&#xff0c;判…

多模态大语言模型和 Apple 的 MM1

原文地址&#xff1a;multimodal-large-language-models-apples-mm1 2024 年 4 月 13 日 抽象是计算机科学中最关键的概念之一&#xff0c;具有一些最强大的影响。从简单的角度来看&#xff0c;抽象就是将某一事物应用于多种不同情况的能力。例如&#xff0c;如果你创造了一种…

【C++】:类和对象(下)

目录 一&#xff0c;再谈构造函数1.初始化列表2. 隐式类型转换的过程及其优化3. 隐式类型转换的使用4. explcit关键字5. 单参数和多参数构造函数的隐式类型转换 二&#xff0c;static成员1.静态成员变量2.静态成员函数3. static 成员的应用 三&#xff0c;友元3.1 友元函数3.2 …

Colab - Introduction to Object Detection using TensorFlow Hub

Colab - Introduction to Object Detection using TensorFlow Hub 1. 源由2. TensorFlow Hub3. 目标检测3.1 举例 - EfficientDet/D4 COCO 20173.2 下载示例图像3.2.1 显示部分样本3.2.2 定义一个将类别ID映射到类别名称和颜色的字典 3.3 加载模型3.4 单张照片执行推理3.4.1 推…

网络基础(全)

协议 ”协议“就是一种约定。那么协议需要需要管理吗&#xff1f;答案是当然需要管理呀。 操作系统要进行协议管理——先描述&#xff0c;在组织协议本质就是软件&#xff0c;软件是可以进分层的协议在设计的时候&#xff0c;就是被层状的划分的为什么要划分为层状结呢&#…

TCP的特性(4)

TCP特性 拥塞控制(可靠性机制)延迟应答(效率机制)捎带应答(效率机制)面向字节流(粘包问题)TCP异常机制小结 拥塞控制(可靠性机制) 虽然TCP引入了滑动窗口,能够高效可靠的传输大量数据,但是在开始阶段就发送大量数据,可能引起一系列问题. TCP引入了慢启动机制,先发少量的数据,判…

PS 2018

软件安装 文件太大&#xff0c;分批上传了&#xff0c;后续下载下来文件目录是这样的&#xff0c; 三个文件夹.7z 分批上传&#xff0c;exe也压缩分批上传&#xff0c; 其中products文件夹太大&#xff0c;里面子目录继续压缩分批上传 都下好了&#xff0c;就exe执行安装就行…

分层图像金字塔变压器

文章来源&#xff1a;hierarchical-image-pyramid-transformers 2024 年 2 月 5 日 本文介绍了分层图像金字塔变换器 (HIPT)&#xff0c;这是一种新颖的视觉变换器 (ViT) 架构&#xff0c;设计用于分析计算病理学中的十亿像素全幻灯片图像 (WSI)。 HIPT 利用 WSI 固有的层次结…

面经总结系列(二): 面壁智能大模型算法工程师

&#x1f468;‍&#x1f4bb;作者简介&#xff1a; CSDN、阿里云人工智能领域博客专家&#xff0c;新星计划计算机视觉导师&#xff0c;百度飞桨PPDE&#xff0c;专注大数据与AI知识分享。✨公众号&#xff1a;GoAI的学习小屋 &#xff0c;免费分享书籍、简历、导图等&#xf…

Mysql基础篇(一)Mysql概述

基本概念 数据库(DataBase,DB) 数据库的定义 按照数据结构来组织、存储和管理数据的仓库。 严格意义上来说&#xff0c;数据库是一个实体&#xff0c;它是能够合理保管数据的“仓库”&#xff0c;用户在该“仓库”中存放要管理的事务数据&#xff0c;“数据”和“库”两个概念…

HTML5+CSS3小实例:无限循环loading动画

实例:无限循环loading动画 技术栈:HTML+CSS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sc…

大数据分析入门之10分钟掌握GROUP BY语法

前言 书接上回大数据分析入门10分钟快速了解SQL。 本篇将会进一步介绍group by语法。 基本语法 SELECT column_name, aggregate_function(column_name) FROM table_name GROUP BY column_name HAVING condition假设我们有students表&#xff0c;其中有id,grade_number,class…

Matlab画箱线图

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

内网安全-代理Socks协议路由不出网后渗透通讯CS-MSF控制上线简单总结

我这里只记录原理&#xff0c;具体操作看文章后半段或者这篇文章内网渗透—代理Socks协议、路由不出网、后渗透通讯、CS-MSF控制上线_内网渗透 代理-CSDN博客 注意这里是解决后渗透通讯问题&#xff0c;之后怎么提权&#xff0c;控制后面再说 背景 只有win7有网&#xff0c;其…

Unity Trail Renderer入门

概述&#xff1a; 在项目的开发过程中&#xff0c;一定有时候需要炫酷的尾迹效果&#xff0c;那接下来这部分的内容&#xff0c;一定不要错过&#xff01; Trail Renderer&#xff08;尾迹渲染&#xff09; Time&#xff1a;尾迹存在的时间&#xff0c;时间越长尾迹存在的越久…

无人机+无人车:自组网协同技术及应用前景详解

无人车&#xff0c;也被称为自动驾驶汽车、电脑驾驶汽车或轮式移动机器人&#xff0c;是一种通过电脑系统实现无人驾驶的智能汽车。这种汽车依靠人工智能、视觉计算、雷达、监控装置和全球定位系统协同合作&#xff0c;使得电脑可以在没有任何人类主动操作的情况下&#xff0c;…

总分420+专业140+哈工大哈尔滨工业大学803信号与系统和数字逻辑电路考研电子信息与通信工程,真题,大纲,参考书。

考研复习一路走来&#xff0c;成绩还是令人满意&#xff0c;专业803信号和数电140&#xff0c;总分420&#xff0c;顺利上岸&#xff0c;总结一下自己这一年复习经历&#xff0c;希望大家可以所有参考&#xff0c;这一年复习跌跌拌拌&#xff0c;有时面对压力也会焦虑&#xff…

【算法系列】字符串

目录 leetcode题目 一、最长公共前缀 二、最长回文子串 三、二进制求和 四、字符串相加 五、字符串相乘 六、仅仅反转字母 七、字符串最后一个单词的长度 八、验证回文串 九、反转字符串 十、反转字符串 II 十一、反转字符串中的单词 III leetcode题目 一、最长公…

[Kubernetes] 安装KubeSphere

选择4核8G&#xff08;master&#xff09;、8核16G&#xff08;node1&#xff09;、8核16G&#xff08;node2&#xff09; 三台机器&#xff0c;按量付费进行实验&#xff0c;CentOS7.9安装Docker安装Kubernetes安装KubeSphere前置环境: nfs和监控安装KubeSphere masternode1no…