Flutter笔记:Widgets Easier组件库(10)快速处理承若型对话
- 文章信息 - Author: 李俊才 (jcLee95)
Visit me at CSDN: https://jclee95.blog.csdn.net
My WebSite:http://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组件库快速处理承若型弹窗。
目 录
1. 概述 1.1 关于Widgets Easier
本库是一个 Flutter 组件库,旨在提供用于Flutter开发的组件,使得开发者能够更简单地构建出更丰富地界面效果。项目地址为:
-
https://github.com/jacklee1995/widgets_easier
-
https://pub.dev/packages/widgets_easier
在你的Flutter项目中,运行下面的命令:
flutter pub add widgets_easier
即可安装最新版本的 Widgets Easier 库。
2. 什么是承若型对话 2.1 基本概念承若型对话是一套带有异步性质的弹窗机制。这种弹窗机制能够广泛运用于处理登录验证等具有未来性质。
一个 Future 对象在其生命周期中有两种状态:
- 未完成(Uncompleted):
当 Future 被创建时,它处于未完成状态。这意味着异步操作尚未完成,结果还不可用。
- 完成(Completed):
异步操作完成后,Future 进入完成状态。这个状态有两种可能的结果:
-
成功(Fulfilled): 异步操作成功完成,Future 获得了一个值。
-
失败(Rejected): 异步操作因错误而未能成功完成,Future 获得了一个错误。
与之对应的,在承若型对话中注重的时过程,也即是更关注 Uncompleted 到 Completed 的过度状态和状态结果。这就是说,在一组承若型对话中至少有三个对话单元(Dialog),分别是
- 加载中;
- 加载完成;
- 加载成功
- 加载失败
以用户登录为例,承若型对话可以被设计为以下三个阶段的对话单元:
- 加载中(Loading):
当用户提交登录信息(如用户名和密码)后,应用会显示一个加载中的对话框或提示。这个阶段对应于 Future 的 未完成(Uncompleted) 状态,表示登录的异步操作正在进行中,结果尚未确定。
- 加载完成(Completion):
这个阶段对应于 Future 的 完成(Completed) 状态,根据操作的结果,可以进一步分为两个子阶段:
- 加载成功(Success):
如果登录验证成功,应用会显示一个成功的提示对话框或者直接跳转到应用的主界面。这表示异步操作成功完成,用户被成功验证。
- 加载失败(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中,包含
status
和data
两个字段; status
的类型为bool
,表示成功或者失败;data
表示是一个字符串,表示成功或者失败时相关消息。
futureCallback
还未实现(fulfill)的过程中,展示的是 LoadingDialog;- 如果
futureCallback
实现(fulfill)后的而己过为成功,则展示 SuccessDialog; - 反之则展示FailureDialog。
现在我们构建一个
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 效果展示
用户名密码为空:
输入错误的密码:
密码认证成功
在之前的内容中,我介绍了FutureDialogs.show的基本用法,这个方法没有动进入画效果。另外有一个 FutureDialogs.zoomIn方法拥有完全一样的接口,但是拥有从小到大的动画效果,看起来就像这样:
如果有需要,你可以使用 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
效果看起来是这样的:
你可以在这个项目的 GitHub 上提供反馈或报告问题。如果你觉得这个库缺少某个功能,请创建一个功能请求。欢迎提交拉取请求。
相关文章:

Flutter笔记:Widgets Easier组件库(10)快速处理承若型对话
Flutter笔记 使用Widgets Easier组件库快速处理承若型对话 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…...
10_Linux中的计划任务
10_Linux中的计划任务 常见计划任务 Linux系统中默认在执行的计划任务 日志文件的轮询:logrotate日志文件分析logwatch任务建立locate数据库建立manpage查询数据库RPM软件日志文件删除缓存与网络有关的分析 仅执行一次的计划任务 atd和at [rootnode4 ~]# systemctl start…...

Google Play开发者账号为什么会被封?如何解决关联账号问题?
Google Play是Google提供的一个应用商店,用户可以在其中下载并安装Android设备上的应用程序、电影、音乐、电子图书等。Google Play是Android平台上较大的应用市场,包含了数百万个应用程序和游戏。但是谷歌对于上架应用的审核越趋严格,开发者…...
(第12天)【leetcode题解】151、反转字符串中的单词
目录 151、反转字符串中的单词题目描述思路代码本题反思 151、反转字符串中的单词 题目描述 给你一个字符串 s ,请你反转字符串中单词的顺序。 单词是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的单词分隔开。 返回单词顺序颠倒且单词之间用单个…...

如何处理多模态数据噪声不均衡动态?天大等最新《低质量数据的多模态融合》综述
多模态融合致力于整合来自多种模态的信息,目的是实现更准确的预测。在包括自动驾驶和医疗诊断等广泛的场景中,多模态融合已取得显著进展。然而,在低质量数据环境下,多模态融合的可靠性大部分仍未被探索。本文综述了开放多模态融合…...

Autosar NvM配置-手动配置Nvblock及使用-基于ETAS软件
文章目录 前言NvDataInterfaceNvBlockNvM配置SWC配置RTE Mapping使用生成的接口操作NVM总结前言 NVM作为存储协议栈中最顶层的模块,是必须要掌握的。目前项目基本使用MCU带的Dflash模块,使用Fee模拟eeprom。在项目前期阶段,应该充分讨论需要存储的内容,包括应用数据,诊断…...

【c++算法篇】双指针(下)
🔥个人主页:Quitecoder 🔥专栏:算法笔记仓 朋友们大家好啊,本篇文章我们来到算法的双指针的第二部分 目录 1.有效三角形的个数2.查找总价格为目标值的两个商品3.三数之和4.四数之和5.双指针常见场景总结 1.有效三角形…...

微图乐 多种装B截图一键制作工具(仅供娱乐交流)
软件介绍 采用exe进程交互通信。全新UI界面,让界面更加清爽简约。支持zfb、VX、TX、Yin行、Dai款、游戏等图片生成,一键超清原图复制到剪辑板,分享给好友。适用于提高商家信誉度,产品销售额度。装逼娱乐,用微图乐。图…...

基于Springboot的点餐平台
基于SpringbootVue的点餐平台的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页展示 菜品信息 菜品资讯 购物车 后台登录 用户管理 菜品分类管理 菜品信息管理 …...
C# 获取一个字符串中非数字部分?
方法一:使用正则表达式 使用正则表达式可以便捷地匹配并提取出字符串中所有非数字字符。与之前保留数字时的做法相反,这次我们将匹配数字并替换为空字符串,从而留下非数字部分。 using System; using System.Text.RegularExpressions;publi…...
今日总结2024/5/7
今日复习LIS二分优化的使用 P2782 友好城市 确定一边城市排序完后,另外一边满足坐标上升的最大数目即是桥的最大个数 为上升子序列模型 #include <iostream> #include <algorithm> #include <utility> #define x first #define y second cons…...

爬虫学习(3)豆瓣电影
代码 import requests import jsonif __name__ "__main__":url https://movie.douban.com/j/chart/top_list#post请求参数处理(同get请求一致)headers {"User-Agent": Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/53…...

GNU Radio创建FFT、IFFT C++ OOT块
文章目录 前言一、GNU Radio官方FFT弊端二、创建自定义的 C OOT 块1、创建 OOT 模块2、创建 OOT 块3、修改 C 和 CMAKE 文件4、编译及安装 OOT 块 三、测试1、grc 图2、运行结果①、时域波形对比②、频谱图对比 四、资源自取 前言 GNU Radio 自带的 FFT 模块使用起来不是很方便…...

125.两两交换链表中的节点(力扣)
题目描述 代码解决及思路 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), …...
APP精准推送广告是怎么做到的?
你有没有遇到这种情况,刚和家人聊起五一去哪玩,各种软件就刷到各地旅游景点。刚和朋友说到健身计划,转眼间网购平台就给你推荐各种健身用品,这些软件是如何知道我们的需求,难道我们的手机被监听了?从技术上…...

RapidJSON介绍
1.简介 RapidJSON 是一个 C 的 JSON 解析库,由腾讯开源。 支持 SAX 和 DOM 风格的 API,并且可以解析、生成和查询 JSON 数据。RapidJSON 快。它的性能可与strlen() 相比。可支持 SSE2/SSE4.2 加速。RapidJSON 独立。它不依赖于 BOOST 等外部库。它甚至…...

大型企业总分支多区域数据传输,效率为先还是安全为先?
大型企业为了业务拓展需要,会在全国乃至全球各地设立分公司和办事机构,以便更好地处理当地事务,并进行市场的开拓和客户维护,此时,企业内部就衍生出了新的业务需求,即多区域数据传输。 多区域很难准确定义&…...

C语言例题35、反向输出字符串(指针方式),例如:输入abcde,输出edcba
#include <stdio.h>void reverse(char *p) {int len 0;while (*p ! \0) { //取得字符串长度p;len;}while (len > 0) { //反向打印到终端printf("%c", *--p);len--;} }int main() {char s[255];printf("请输入一个字符串:");gets(s)…...

场景文本检测识别学习 day09(Swin Transformer论文精读)
Patch & Window 在Swin Transformer中,不同层级的窗口内部的补丁数量是固定的,补丁内部的像素数量也是固定的,如上图的红色框就是不同的窗口(Window),窗口内部的灰色框就是补丁(Patch&#…...

抖音小店个人店和个体店有什么不同?区别问题,新手必须了解!
哈喽~我是电商月月 新手开抖音小店入驻时会发现,选择入驻形式时有三个选择,个人店,个体店和企业店 其中,个人店和个体店只差了一个字,但个人店不需要营业执照,是不是入驻时选择个人店会更好一点呢&#x…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...