Flutter 创建自己的对话框,不使用任何包!

news2024/11/23 16:30:54

创建自己的对话框,不使用任何包!

alt

原文 https://itnext.io/create-your-own-dialog-without-using-any-packages-7bb303f62471

前言

在本文中,我们将学习如何创建我们自己的 showDialog() 函数,并了解到底发生了什么。

正文

先看效果

alt

让我们首先检查 showDialog,看看它里面有什么!

alt

正如您所看到的,showDialog ()所做的就是获取小部件并将其作为 DialogRoute 使用 Navigator 进行推送。没什么特别的!

因此,如果我们想创建一个对话框,我们应该使用导航器和路由,太!

但什么是导航器,为什么我们需要它的对话?

alt

没错,导航器也是个 widget !

毕竟,一切都是一个 widget ,甚至是我,甚至是你,甚至是导航器本身ー匿名 Flutter 开发人员

本质上,Navigator 的工作是管理一堆 Route 对象,并在 Overlay widget 中的 widget 之间进行可视化切换。

什么是叠加,为什么它很重要?

基本上,Overlay 是一种特殊的 Stack widget ,它将应用程序包装在导航器中。

正如您所猜测的,Dialogs 仅仅是 UI 之上的 widget (就像吐司 widget 一样) ,但在这种情况下,导航器明智地使用 Routes 控制它们。这就是为什么他们让我们感觉像别的东西。

是的,我们也可以仅仅使用 Overlay widget 创建我们自己的 widget ,但是我们也想与导航器交互,因为我们不想重新发明轮子!如果我们不用领航员的话。我们必须处理所有的过渡、生命周期、后退按钮、可取消的障碍等等。

这就是为什么我们也应该知道路线!

记住,showDialog() 也使用 DialogRoute 是有原因的。

但是对话路由有什么特别之处呢?

alt

对话路由继承模式

对话路线的超能力来自于它的祖先! 让我来告诉你怎么做!

让我们看看,在每一步,我们继承了什么!

Route -> A basic route

“Route is a base class that interacts with the navigator.”
OverlayRoute -> A route that knows how to interact with Overlay

“A route that displays widgets in the Navigator’s Overlay.”
TransitionRoute -> A route that can do a magic trick

“A route with entrance and exit transitions.”
ModalRoute -> A route that has a barrier behind it

“A route that blocks interaction with previous routes.”
PopupRoute -> A route that shows up over the current route

“A modal route that overlays a widget over the current route.”
RawDialogRoute -> A pre-configured route for dialogs

“A general dialog route which allows for customization of the dialog popup.”
DialogRoute -> A ready-to-use, pre-designed route

“A dialog route with Material entrance and exit animations, modal barrier color, and modal barrier behavior”

(这些句子都参考了官方的 api 文档。)

这里的教训是: 当我们调用 showDialog() ,它调用导航器.push() ,当导航器推动某些东西,如果它是 PopupRoute,它得到生命周期(来自导航器) ,家庭(来自 OverlayRoute) ,过渡(来自过渡路线) ,障碍(来自 ModalRoute) ,并出现在路线上(来自自身)。

无论如何,如果我们得到了主要的想法,让我们看看代码,并学习如何创建我们自己的对话框!

对话框例子

1. 设计一个对话框

创建自己的对话框小部件

// Just a simple custom dialog, nothing special
class CustomDialog extends StatelessWidget {
  const CustomDialog({
    super.key,
    required this.title,
    required this.description,
    required this.confirmText,
    this.onTap,
  });

  final String title;
  final String description;
  final String confirmText;
  final void Function()? onTap;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Padding(
        padding: const EdgeInsets.all(32),
        child: Material(
          elevation: 4,
          borderRadius: const BorderRadius.all(Radius.circular(16)),
          child: Padding(
            padding: const EdgeInsets.all(24),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Text(
                  title,
                  style: const TextStyle(
                    fontSize: 20,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 12),
                Text(
                  description,
                  style: const TextStyle(color: Colors.grey),
                ),
                const SizedBox(height: 32),
                SizedBox(
                  width: double.infinity,
                  child: CupertinoButton.filled(
                    onPressed: onTap,
                    child: Text(confirmText),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

2. 创建自己的对话框

在这个例子中,我将使用 PopupRoute 来制作我自己的配置。如果需要预先配置的 Dialogs,可以使用 RawDialogRoute 或 DialogRoute,就像 showDialog ()所做的那样。

// Custom Dialog implementation
class CustomDialogRoute<Textends PopupRoute<T{
  CustomDialogRoute({
    required this.builder,
    super.settings,
  });
  // We're getting a widget with context
  final Widget Function(BuildContext context) builder;

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    // return just a static widget
    return builder(context);
  }

  @override
  Widget buildTransitions(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
    Widget child,
  ) {
    // random animations go 🔪 🔪 🔪
    return RotationTransition(
      turns: Tween<double>(begin: 0.25, end: 0).animate(animation),
      child: ScaleTransition(
        scale: animation,
        child: child,
      ),
    );
  }

  @override
  Color? get barrierColor => Colors.black.withOpacity(.65);

  @override
  bool get barrierDismissible => true;

  @override
  Stringget barrierLabel => 'CustomDialog';

  @override
  Duration get transitionDuration => const Duration(milliseconds: 250);
}

3. 为可重用代码创建 showCustomDialog 方法

为了让事情变得更简单,我把它变成了一种延伸。

extension DialogExtension on BuildContext {
  Future<T?> showCustomDialog<T extends Object?>(
    Widget child, {
    RouteSettings? settings,
  }) {
    return Navigator.of(this).push<T>(
      CustomDialogRoute<T>(
        builder: (_) => child,
        settings: settings,
      ),
    );
  }
}

4. 想在哪里用就在哪里用!

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            context.showCustomDialog(
              CustomDialog(
                title: 'Hello Fellow!',
                description: "Don't you think Flutter is awesome?",
                confirmText: 'Absolutely!',
                onTap: () {
                  debugPrint('agreed');
                  Navigator.pop(context);
                },
              ),
            );
          },
          child: const Text('Show Dialog'),
        ),
      ),
    );
  }
}

代码

https://github.com/rei-codes/custom_dialog_example

结束语

如果本文对你有帮助,请转发让更多的朋友阅读。

也许这个操作只要你 3 秒钟,对我来说是一个激励,感谢。

祝你有一个美好的一天~


© 猫哥

  • 微信 ducafecat

  • https://wiki.ducafecat.tech

  • https://video.ducafecat.tech

本文由 mdnice 多平台发布

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

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

相关文章

Matplotlib 可视化50图:散点图(1)

导读 本系列将持续更新50个matplotlib可视化示例&#xff0c;主要参考Selva Prabhakaran 在MachineLearning Plus上发布的博文&#xff1a;Python可视化50图。 定义 关联图是查看两个事物之间关系的图像&#xff0c;它能够展示出一个事物随着另一个事物是如何变化的。关联图的类…

ctfshow(菜狗杯)

目录 web签到 一言既出 驷马难追 web2 c0me_t0_s1gn 我的眼里只有$ TAPTAPTAP Webshell 化零为整 无一幸免 遍地飘零 传说之下&#xff08;雾&#xff09; Is_Not_Obfuscate web签到 <?phperror_reporting(0); highlight_file(__FILE__);eval($_REQUEST[$_GET[…

springboot大学生课堂考勤管理系统的设计与实现

根据一般学生课堂考勤管理系统的功能需求分析&#xff0c;本系统的功能模块如下&#xff1a; &#xff08;1&#xff09;在个人中心&#xff0c;管理员可以修改自己的用户名和登录密码。 &#xff08;2&#xff09;在学生管理模块中&#xff0c;可以查看学生的信息&#xff0c;…

DiffusionDet:Diffusion Model for Object Detection

Diffusion Model for Object Detection 一种用于目标检测的扩散模型 Motivation 1、如何使用一种更简单的方法代替可查询的object queries 2、Bounding box的生成方式过去是三种&#xff0c;第一种为sliding windows、第二种anchor box、第三种object queries&#xff0c;这里其…

AlphaFold2源码解析(3)--数据预处理

AlphaFold2源码解析(3)–数据预处理 数据预处理整体流程 数据处理入口&#xff1a; feature_dict data_pipeline.process( input_fasta_pathfasta_path,# 输入序列目录 msa_output_dirmsa_output_dir) # MSA序列目录 可能是单体也可能是多聚体 主要调动的API是&#xff1a; …

如何让Java项目兼容更多的客户端设备(二)

如何让Java项目兼容更多的客户端设备&#xff08;二&#xff09; ​ ​ 一、Token认证的原理 传统的单体JavaWeb项目通常采用HttpSession保存登陆成功的凭证&#xff0c;但是HttpSession需要浏览器的Cookie机制配合。也就是说Web项目的客户端只能是浏览器&#xff0c;不可以…

torch.nn.functional.grid_sample(F.grid_sample)函数的说明 3D空间中的点向图像投影的易错点

由于二者有一定共通之处&#xff0c;因此放在一篇文章内介绍。 1. 关于torch.nn.functional.grid_sample函数的说明&#xff08;F.grid_sample&#xff09; 该函数的作用是在图像/体素空间中采样特征。 1.1 输入和输出&#xff1a; 变量名数据类型默认值含义备注inputTensor-…

训练神经网络的各种优化算法【文末赠书】

正确的优化算法可以成倍地减少训练时间 许多人在训练神经网络时可能会使用优化器&#xff0c;而不知道该方法称为优化。优化器是用于更改神经网络属性&#xff08;例如权重和学习率&#xff09;以减少损失的算法或方法。 文章目录梯度下降随机梯度下降小批量梯度下降其它优化算…

C/C++指针之提高篇详解(二)

一、引言 C/C语言中引入了指针&#xff0c;使得程序能够直接访问内存地址&#xff0c;使得很多复杂的操作变得简单&#xff0c;同时也提高了程序的运行效率。指针即是地址&#xff0c;但是地址却是通过指针变量来存储的。这就好比我们的教室&#xff0c;每个教室都有一个房间号…

第3章 Tomcatservlet

1.BS与CS *CS&#xff1a;客户端服务器架构模式 优点&#xff1a;充分利用客户端机器的资源&#xff0c;减轻服务器的负荷 缺点&#xff1a;需要安装&#xff1b;升级维护成本较高 *BS&#xff1a;浏览器服务器架构模式 优点&#xff1a;客户端不需要安装&#xff0c;维护成本…

Zlibrary已死,找了一个替代品,找了一个替代品免费的电子书下载平台...

大家好&#xff0c;我是鸟哥。一个半路出家的程序员。 提到Zlibrary&#xff0c;想必大家都不陌生吧。全球最大的数字图书馆&#xff0c;截止被封前共收录了591万本书&#xff0c;7751万篇文章&#xff0c;并且还在不断的增加中&#xff0c;关键是可以免费下载。 反正我是很熟悉…

Rust之常用集合(二):字符串(String)

开发环境 Windows 10Rust 1.65.0VS Code 1.73.1 项目工程 这里继续沿用上次工程rust-demo 用字符串存储UTF-8编码的文本 我们在之前的章节中讨论了字符串&#xff0c;但现在我们将更深入地研究它们。新的Rust人会因为三个原因而陷入字符串:Rust倾向于暴露可能的错误&#x…

【季报分析】美团:真的很美

11月25日&#xff0c;港股盘后美团发布了2022年第三季度业绩报告。整体来看&#xff0c;财报数据还算不错&#xff0c;毕竟大部分指标都已经超预期&#xff0c;探员利用这两天假期&#xff0c;把美团的这份财报仔细过了一遍&#xff0c;当然探员也把2022年Q1、Q2的数据也进行了…

Linux代码调试----gdb使用介绍

目录 一、简介 二、gdb使用流程&#xff1a; &#xff08;1&#xff09;gdb的启动 &#xff08;2&#xff09;调试中查看源代码 &#xff08;3&#xff09;开始调试 一、简介 GDB 全称“GNU symbolic debugger”&#xff0c;是 Linux 下常用的程序调试器。发展至今&#xff…

[附源码]SSM计算机毕业设计校园超市进销存管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Node.js】第九章 数据库

目录 1. 数据库的基本概念 1.1 数据库的概念 1.2 数据库的分类 1.3 数据组织结构 2. MySQL使用介绍 2.1 安装MySQL和MySQL Workbench 2.2 MySQL的基本使用 2.3 使用SQL管理数据库 3. 在项目中使用MySQL 3.1 安装和配置MySQL模块 3.2 操作数据 1. 数据库的基本概念…

word怎么转pdf?word转pdf借助pdf软件即可搞定!

我们在办公的时候&#xff0c;会有word转pdf的办公需求&#xff0c;但是很多人都不清楚word转pdf的方法&#xff0c;那么word怎么转pdf呢&#xff1f;其实方法很简单&#xff0c;利用pdf软件来进行word转pdf的操作即可&#xff0c;如今&#xff0c;市面上pdf软件应接不暇&#…

五、Javascript 空间坐标[尺寸、滑动]

一、尺寸 1.视窗尺寸 document.documentElement.clientWidth&#xff1a;视窗宽度document.documentElement.clientHeight&#xff1a;视窗高度 2.各种尺寸 举例&#xff1a;<div id"gao"></div> 前提&#xff1a;var a document.getElementById(g…

多重共线性如何分析?

判断标准 常见的直观判断方法共有四个&#xff0c;如下&#xff1a; &#xff08;1&#xff09;某些自变量的相关系数值较大&#xff08;比如大于0.8&#xff09;等&#xff0c;可以利用pearson相关系数检验法一般是利用解释变量之间的线性相关程度判断&#xff0c;一般标准是…

Java常用类(二)

目录 JDK8之前的日期时间API java.lang.System类 java.util.Date类 两个构造器的使用 两个方法的使用 java.sql.Date类 涉及两个问题&#xff1a; java.text.SimpleDateFormat类 格式化&#xff1a;日期--->字符串 解析&#xff1a;字符串--->日期&#xff08;格…