我們在使用flutter的過程中,有時候需要控制某些元件是否展示,一種方法是將這個元件從render tree中刪除,這樣這個元件就相當於沒有出現一樣,但是有時候,我們只是不想展示這個widget,但是這個元件還是存在的,並且可以接受鍵盤輸入,還可以使用CPU。它和真正的元件唯一不同的就是他是不可見的。
這樣的元件就叫做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需要一個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