写点什么

flutter 系列之:flutter 中的 offstage

作者:程序那些事
  • 2022 年 6 月 23 日
  • 本文字数:1920 字

    阅读完需:约 6 分钟

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

发布于: 刚刚阅读数: 3
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
flutter系列之:flutter中的offstage_flutter_程序那些事_InfoQ写作社区