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

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

效果看起来是这样的:

在这里插入图片描述

F. 报告问题和贡献代码

你可以在这个项目的 GitHub 上提供反馈或报告问题。如果你觉得这个库缺少某个功能,请创建一个功能请求。欢迎提交拉取请求。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IoTDB 入门教程 基础篇⑦——数据库管理工具 | DBeaver 连接 IoTDB

文章目录 一、前文二、下载iotdb-jdbc三、安装DBeaver3.1 DBeaver 下载3.2 DBeaver 安装 四、安装驱动五、连接数据库六、参考 一、前文 IoTDB入门教程——导读 二、下载iotdb-jdbc 下载地址org/apache/iotdb/iotdb-jdbc&#xff1a;https://maven.proxy.ustclug.org/maven2/o…

ai可以做思维导图吗?当然是可以的!

ai可以做思维导图吗&#xff1f;在快节奏的现代生活中&#xff0c;思维导图作为一种高效的信息组织和表达工具&#xff0c;越来越受到人们的青睐。随着人工智能&#xff08;AI&#xff09;技术的不断发展&#xff0c;AI思维导图软件也应运而生&#xff0c;它们不仅能够帮助用户…

为什么现在越来越多的人会选择陪诊

现在越来越多的人选择陪诊的原因有多方面。 首先&#xff0c;随着人口老龄化、医疗资源分配不均等问题的日益突出&#xff0c;许多老年人和病患在就医过程中面临诸多困难&#xff0c;如挂号、排队、取药等繁琐的手续和流程。陪诊服务能够为他们提供极大的便利&#xff0c;帮助…

【Gateway远程开发】0.5GB of free space is necessary to run the IDE.

【Gateway远程开发】0.5GB of free space is necessary to run the IDE. 报错 0.5GB of free space is necessary to run the IDE. Make sure that there’s enough space in following paths: /root/.cache/JetBrains /root/.config/JetBrains 原因 下面两个路径的空间不…

【excel】统计单元格内数字/字符串的数量

文章目录 一、问题二、步骤&#xff08;一&#xff09;将A1中的数字分解出来&#xff0c;在不同的单元格中显示&#xff08;二&#xff09;统计每个数字出现的个数&#xff08;三&#xff09;去重 三、尾巴 一、问题 单元格中有如下数值&#xff1a;12345234534545&#xff0c…

Nginx(参数设置总结)

文章目录 Nginx&#xff08;工作机制&参数设置&#xff09;1.Master&Worker工作机制1.示意图2.解释3.Nginx争抢机制4.accept_mutex解决惊群现象5.多进程结构不用多线程结构的好处6.IO多路复用&#xff0c;实现高并发7.优势 2.参数配置1.work_processes1.基本介绍2.work…

Javaweb项目 博客系统(后端代码编写)

准备工作,创建项目 引入依赖 1.servlet 2.mysql 3.jackson 导入前端代码 1.博客列表页 2.博客详情页 3.登录页 4.博客编辑页 接下来要进行的操作就是两大方面 1.前端和服务器的交互 2.服务器和数据库的交互 进行数据库设计创建数据库和数据表 一把需要把建库建表的操作写错sq…

C语言实验-数组、字符串以及指针

一&#xff1a; 求一个NN矩阵主、次对角线上所有元素之和。矩阵输入、矩阵输出、矩阵对角线求和分别用三个子函数实现。&#xff08;N的值由用户从键盘输入&#xff09; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h>void print(int(*arr…

323_C++_QT_QProcess执行cmd解压、压缩、删除tar.gz等等其他压缩包文件到指定目录,不需要外部库,QT自带API的就行

// decompressPath : 解压到此目录 // fileName : 解压的tar.gz文件名executeCommand(decompressPath , QString::fromStdString(fileName));// 开始解压 void executeCommand

获取和修改线程的id和名称

当创建两个线程时&#xff0c;需要获取线程的id和名称&#xff0c;这样可以知道是哪个线程执行的 方式1&#xff1a;this.getId()和this.getName() 写代码注意点&#xff1a;要写对类名 方式2&#xff1a;Thread.currentThread().getId()和Thread.currentThread().getName() 修…

初识Node.js-REPL(详解交互式解释器)

目录 一、REPL介绍 1.概念 2.主要特点和用途 3.应用 二、 REPL语法 1.简单的表达式运算 2.使用变量 3.多行表达式 下划线(_)变量 三、REPL 命令 四、停止 REPL 五、Gif 实例演示 六、REPL应用实例 七、总结 一、REPL介绍 1.概念 Read&#xff08;读取&#xff09…

类和对象、this指针、类里的默认生成函数

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

如何恢复回收站中被删除的文件?3个恢复策略,实测有用!

“刚刚一不小心把回收站清空了&#xff0c;大家有什么好用的方法可以帮我恢复回收站中删除的文件吗&#xff1f;快帮帮我吧&#xff01;” 在使用电脑的过程中&#xff0c;我们有时可能会不小心将重要的文件或文件夹删除到回收站&#xff0c;并且随后可能进一步从回收站中彻底删…

【Git】Git学习-17:git rebase,且解决合并冲突

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 理论 git rebase 目标分支&#xff1a;把当前分支的提交&#xff0c;从与目标分支的共同主祖先处断开…

【linux】dmesg工具

dmesg介绍 dmesg工具用途&#xff1a; dmesg - print or control the kernel ring buffer kernel ring buffer, 内核环形缓冲区&#xff0c;也叫环形队列&#xff0c;Linux内核日志就存储在一个环形队列中&#xff0c;环形队列满的时候&#xff0c;新的消息会覆盖掉旧的消息。…

UE5自动生成地形一:地形制作

UE5自动生成地形一&#xff1a;地形制作 常规地形制作地形编辑器地形管理添加植被手动修改部分地形的植被 置换贴图全局一致纹理制作地貌裸露岩石地形实例 常规地形制作 地形制作入门 地形导入部分 选择模式&#xff1a;地形模式。选择地形子菜单&#xff1a;管理->导入 …

Windows电脑搭建HarmonyOS NEXTDeveloper Preview2环境详解

Windows电脑搭建HarmonyOS NEXTDeveloper Preview2环境详解&#xff1a; HarmonyOS NEXT Preview系列教程基于Api11讲解-IT营大地老师 1 、电脑要求以及注意事项 操作系统 &#xff1a; Windows10 64 位、 Windows11 64 位 内存 &#xff1a; 8GB 及以上&#xff0c;推荐 16G…

“情况不明,对子先行”攻略

掼蛋作为一种策略性极强的游戏&#xff0c;不仅考验牌技&#xff0c;更考验玩家的智慧和策略布局。这里主要介绍一下当牌力不足的时候的普通策略—情况不明&#xff0c;对子先行。 当你的牌力不强&#xff0c;或者牌局情况不明朗时&#xff0c;自己手上有有比较多的对子&#x…

【Ansible】ansible-playbook剧本

playbook 是ansible的脚本 playbook的组成 1&#xff09;Tasks&#xff1a;任务&#xff1b;通过tasks 调用ansible 的模板将多个操作组织在一个playbook中运行 2&#xff09;Variables&#xff1a;变量 3&#xff09;Templates&#xff1a;模板 4&#xff09;Handles&#xf…

如何开发自己的深度学习优化算法

深度学习优化算法 如何开发自己的深度学习优化算法理解优化算法的基础**核心组件**&#xff1a; 设计自定义优化算法的步骤**步骤 1: 定义问题和目标****步骤 2: 研究现有算法****步骤 3: 开发初步想法****步骤 4: 创建原型****步骤 5: 系统测试与优化** 关键建议 如何开发自己…