'Visibility vs Offstage vs Opacity, which is best in hiding a child from widget tree?
From this thread I found that there are many ways of hiding a widget from the tree hierarchy. Like using:
Visibility
:
Visibility(
visible: false,
child: Foo(),
);
Offstage
:
Offstage(
offstage: true,
child: Foo(),
);
Opacity
:
Opacity(
opacity: 0,
child: Foo(),
);
if
condition:
if (visible) {
child
}
and what not.
Which one of them is preferred (I know Visibility
is the one, by why Visibility
), what's the difference between if
condition and Visibility
, how do I measure the performance. Opacity
docs mentions:
Opacity is more efficient than adding and removing the child widget from the tree on demand.
What does that mean, was it for if
condition? If yes, where does if
stand then among the four?
Solution 1:[1]
Opacity
This one sets the opacity (alpha) to anything you want. Setting it to 0.0
is just slightly less visible than setting it to 0.1
, so hopefully that's easy to understand. The widget will still maintain its size and occupy the same space, and maintain every state, including animations. Since it leaves a gap behind, users can still touch it or click it. (BTW, if you don't want people to touch an invisible button, you can wrap it with an IgnorePointer
widget.)
Offstage
This one hides the child widget. You can imagine it as putting the widget "outside of the screen" so users won't see it. The widget still goes through everything in the flutter pipeline, until it arrives at the rendering stage, where it doesn't layout or paint anything at all. This means it will maintain all the state and animations, but just won't occupy any space during "layout stage", and won't draw anything during "paint stage". Because it leaves no gap behind, naturally users cannot click it.
Visibility
This one combines the above (and more) for your convenience. It has parameters like maintainState
, maintainAnimation
, maintainSize
, maintainInteractivity
etc. Depending on how you set those properties, it decides from the following:
if you want to maintain state, it will either wrap the child with an
Opacity
or with anOffstage
, depends on whether you also want to maintain size. Further, unless you want tomaintainInteractivity
, it will also wrap anIgnorePointer
for you, because clicking on a transparent button is kinda weird.if you don't want to
maintainState
at all, it directly replaces thechild
with aSizedBox
so it's completely gone. You can change the blankSizedBox
to anything you want, with thereplacement
property.
Removing Widget
If you don't need to maintain states and etc, it's usually recommended to completely remove the widget from the tree. For example, you can use if (condition)
to decide whether to include a widget in a list, or use condition ? child : SizedBox()
to replace it with a SizedBox
directly. This avoid unnecessary calculations and is the best for performance.
Solution 2:[2]
I think the above answer is very useful and clear. About using condition way, I introduce 2 ways very useful:
condition ? child : SizedBox()
orif (condition) child
if you using dart ver at least 2.3.0
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Quyen Anh Nguyen |