flutter 系列之:flutter 中的幽灵offstage
简介
我们在使用flutter的过程中,有时候需要控制某些组件是否展示,一种方法是将这个组件从render tree中删除,这样这个组件就相当于没有出现一样,但是有时候,我们只是不想展示这个widget,但是这个组件还是存在的,并且可以接受键盘输入,还可以使用CPU。它和真正的组件唯一不同的就是他是不可见的。
这样的组件就叫做Offstage。 今天给大家详细介绍一下Offstage的使用。
Offstage详解
我们首先来看下Offstage的定义:
class Offstage extends SingleChildRenderObjectWidget
可以看到,Offstage是一个包含单个child的Widget。接下来看下它的构造函数:
  const Offstage({ Key? key, this.offstage = true, Widget? child })
    : assert(offstage != null),
      super(key: key, child: child);
Offstage主要包含两个属性,分别是表示是否是offstage状态的bool值offstage,如果offstage=true,那么Offstage的子child就会处于隐藏状态。这时候子child不会占用任何空间。
剩下的一个属性就是child了。
那么Offstage是如何控制child是否offstage的呢?
我们看下它的createRenderObject方法:
  RenderOffstage createRenderObject(BuildContext context) => RenderOffstage(offstage: offstage);
可以看到返回的是一个RenderOffstage对象,其中接受一个offstage参数。
如果深入研究RenderOffstage的话,可以看到他的paint方法是这样的:
  void paint(PaintingContext context, Offset offset) {
    if (offstage)
      return;
    super.paint(context, offset);
  }
如果offstage是true的话,paint方法直接返回,不会进行任何的绘制。这也就是Offstage的秘密。
Offstage的使用
从上面讲解的Offstage的构造函数我们知道,Offstage需要一个bool的offstage属性。所以这个offstage属性是可以变换的,从而触发offstage的不同状态。
因为offstage需要这样的一个状态,所以我们在使用offstage的时候,一般来说是创建一个StatefulWidget,从而在StatefulWidget中保持这样的一个offstage属性。
比如我们创建一个OffstageApp,这是一个StatefulWidget,在它的createState方法中,返回一个State<OffstageApp>对象,在createState方法中,我们定义一个_offstage属性。
通过使用这个_offstage,我们可以创建Offstage如下:
Offstage(
          offstage: _offstage,
          child: SizedBox(
            key: _key,
            width: 150.0,
            height: 150.0,
            child: Container(
              color: Colors.red,
            ),
          ),
        )
这里我们设置Offstage的offstage为刚刚设置的_offstage。
另外为了展示方便,我们将Offstage的child设置为一个SizedBox,里面包含了一个红色的Container。
SizedBox包含了width和height属性,方便我们后续的测试。
默认情况下,因为_offstage=true,所以这个Offstage是不可见的,那么怎么将其可见呢?
我们提供一个ElevatedButton,在它的onPressed方法中,我们调用setState方法来修改_offstage,如下所示:
ElevatedButton(
          child: const Text('切换offstage'),
          onPressed: () {
            setState(() {
              _offstage = !_offstage;
            });
          },
        ),
另外,我们还需要一个ElevatedButton来检测Offstage的大小,看看在_offstage发生变化的时候,Offstage到底会不会发生变化。
 ElevatedButton(
              child: const Text('检测SizedBox大小'),
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(
                    content:
                    Text('SizedBox is ${_getSizedBoxSize()}'),
                  ),
                );
              })
这里的_getSizedBoxSize实现如下:
  Size _getSizedBoxSize() {
    final RenderBox renderBox =
    _key.currentContext!.findRenderObject()! as RenderBox;
    return renderBox.size;
  }
我们通过Offstage的_key,来获取到它的Context,从而找到对应的RenderBox,拿到它的大小。
好了,这样我们的代码就写好了,最后将OffstageApp放到Scaffold中运行,我们可以得到下面的界面:

默认Offstage是不会展示的。
如果我们点击下面的检测SizeBox大小的按钮,可以得到下面的界面:

可以看到虽然Offstage没有展示,但是还是获取到了它的大小。
然后我们点击切换Offstage按钮,可以得到下面的界面:

界面完美的展示了。
总结
Offstage是一个非常方便的组件,可以用来隐藏我们不需要展示的组件,但是仍然可以获得它的大小。
本文的例子:https://github.com/ddean2009/learn-flutter.git
flutter 系列之:flutter 中的幽灵offstage的更多相关文章
- flutter系列之:flutter架构什么的,看完这篇文章就全懂了
		
目录 简介 Flutter的架构图 embedder engine Flutter framework Widgets Widgets的可扩展性 Widgets的状态管理 渲染和布局 总结 简介 Fl ...
 - flutter系列之:flutter中常用的container layout详解
		
目录 简介 Container的使用 旋转Container Container中的BoxConstraints 总结 简介 在上一篇文章中,我们列举了flutter中的所有layout类,并且详细介 ...
 - flutter系列之:flutter中常用的Stack layout详解
		
[toc] 简介 对于现代APP的应用来说,为了更加美观,通常会需要用到不同图像的堆叠效果,比如在一个APP用户背景头像上面添加一个按钮,表示可以修改用户信息等. 要实现这样的效果,我们需要在一个Im ...
 - flutter系列之:Material中的3D组件Card
		
目录 简介 Card详解 Card的使用 总结 简介 除了通用的组件之外,flutter还提供了两种风格的特殊组件,其中在Material风格中,有一个Card组件,可以很方便的绘制出卡片风格的界面, ...
 - flutter系列之:flutter中可以建索引的栈布局IndexedStack
		
目录 简介 IndexedStack简介 IndexedStack的使用 总结 简介 之前我们介绍了一个flutter的栈结构的layout组件叫做Stack,通过Stack我们可以将一些widget ...
 - flutter系列之:flutter中常用的GridView layout详解
		
目录 简介 GridView详解 GridView的构造函数 GridView的使用 总结 简介 GridView是一个网格化的布局,如果在填充的过程中子组件超出了展示的范围的时候,那么GridVie ...
 - flutter系列之:flutter中常用的ListView layout详解
		
目录 简介 ListView详解 ListView中的特有属性 ListView的构造函数 ListView的使用 总结 简介 ListView是包含多个child组件的widget,在ListVie ...
 - Flutter系列博文链接
		
Flutter系列博文链接 ↓: Flutter基础篇: Flutter基础篇(1)-- 跨平台开发框架和工具集锦 Flutter基础篇(2)-- 老司机用一篇博客带你快速熟悉Dart语法 Flutt ...
 - flutter系列之:用来管理复杂状态的State详解
		
目录 简介 StatefuWidget和State State的生命周期 总结 简介 Flutter的基础是widget,根据是否需要跟用户进行交互,widget则可以分为StatelessWidge ...
 
随机推荐
- Spring5完整版详解
			
1.Spring 1.1简介 2002,首次退出来Spring框架的雏形:interface21框架 Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,与2004年 ...
 - Taurus.MVC 微服务框架 入门开发教程:项目集成:1、服务端:注册中心、网关(提供可运行程序下载)。
			
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
 - 设置 Git 用户名和邮箱
			
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址.因为每一个提交都会使用这些信息,如果你不完善它们,在 GitHub 远程仓库里很有可能没有你的贡献统计. 以下操作需要你打开 Git ...
 - idea+SpringBoot使用过程中的问题集合
			
1.跨域访问外部接口? 使用Nginx代理(详细参见:https://www.cnblogs.com/ZhaoHS/p/16594619.html): 合并部署,统一从后端访问第三方接口(合并部署详见 ...
 - Python自学笔记6-列表有哪些常用操作
			
列表是Python中最重要的数据类型,它使用的频率非常非常的高,最大程度的发挥Python的灵活性. 和字符串一样,列表的操作方法也有很多.如果说一头钻进去,可能会导致学习没有重点.在这篇文章当中,首 ...
 - 面试突击80:说一下 Spring 中 Bean 的生命周期?
			
Java 中的公共类称之为 Bean 或 Java Bean,而 Spring 中的 Bean 指的是将对象的生命周期,交个 Spring IoC 容器来管理的对象.所以 Spring 中的 Bean ...
 - 如何在 Jenkins CI/CD 流水线中保护密钥?
			
CI/CD 流水线是 DevOps 团队软件交付过程的基本组成部分.该流水线利用自动化和持续监控来实现软件的无缝交付.通过持续自动化,确保 CI/CD 流水线每一步的安全性非常重要.在流水线的各个阶段 ...
 - 无线配置多一个路由器作为家庭wifi的无线热点?
			
以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/ 手头上有个 MERCURY 的破旧路由器,怎么配置它,让它作为 ...
 - 依赖项安全检测新利器:Scorecard API
			
Scorecard 是 OpenSSF 旗下的开源项目,用于评估开源软件风险,本文由该项目的主要贡献者 Naveen 撰写. 现代软件是建立在数百个甚至数千个第三方开源组件之上的,这些通常被称为依赖项 ...
 - MinIO 快速入门指南
			
官方文档地址:http://docs.minio.org.cn/docs/ MinIO 是在 GNU Affero 通用公共许可证 v3.0 下发布的高性能对象存储. 它是与 Amazon S3 云存 ...