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 ...
随机推荐
- java-重载、包修饰词以及堆栈管理
1.方法的重写(Override):重新写.覆盖 1)发生在父子类中,方法名称相同,参数列表相同,方法体不同 2)重写方法被调用时,看对象的类型2.重写与重载的区别: 1)重写(Override): ...
- HEXO-admin安装和使用(汉化版)
hi,大家好,我是KINGWDY,众所周知我用的是hexo,写博文首先要在终端输入hexo n xxxxx,然后打开MWeb PRO开始写md,但是,这很麻烦,就在我一筹莫展之际,我看到了这篇博文-- ...
- HCNP Routing&Switching之DHCP安全
前文我们了解了MAC地址防漂移技术,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/16632239.html:今天我们来了解下DHCP安全相关话题: 回顾DHC ...
- JUC锁:核心类AQS源码详解
目录 1 疑点todo和解疑 2 AbstractQueuedSynchronizer学习总结 2.1 AQS要点总结 2.2 细节分析 2.2.1 插入节点时先更新prev再更新前驱next 2.2 ...
- torch.max与torch.argmax
形式: torch.max(input) → Tensor 返回输入tensor中所有元素的最大值: a = torch.randn(1, 3) >>0.4729 -0.2266 -0.2 ...
- AOP实现系统告警
工作群里的消息怕过于安静,又怕过于频繁 一.业务背景 在开发的过程中会遇到各种各样的开发问题,服务器宕机.网络抖动.代码本身的bug等等.针对代码的bug,我们可以提前预支,通过发送告警信息来警示我们 ...
- Nginx相关模块学习使用实践指南
转载自:https://www.bilibili.com/read/cv16150654?spm_id_from=333.999.0.0 0x01 Nginx 常用模块使用实践 官方模块使用手册:ht ...
- 重要参考步骤---ProxySQL Cluster 集群搭建步骤
环境 proxysql-1:192.168.20.202 proxysql-2:192.168.20.203 均采用yum方式安装 # cat <<EOF | tee /etc/yum.r ...
- Java容器化参数配置最佳实践
Java是以VM为基础的,而云原生讲究的就是Native,天然的矛盾,虽然Quarkus是为GraalVM和HotSpot量身定制的K8s Native Java框架,生态原因切换成本太高,这种矛盾体 ...
- Beats:Beats在Kibana中的集中管理
我们可以通过在命令行中对我们的Beats进行管理,比如我们可以启动metric几个模块,我们可以通过如下的命令来执行: ./metricbeat modules enable apache mysql ...