AlgoInsight

Q&A

How to show and hide widgets in Flutter

By AlgoInsight Team2026-06-07data-structures

Overview

"Hiding" a widget can mean three different things in a layout: remove it completely (no space taken), keep its space but make it invisible, or keep it built but not painted. Flutter offers a tool for each, plus the simplest approach - conditional construction - where you just don't put the widget in the tree at all. State drives it: flip a bool and call setState to rebuild.

graph TD
    A[Want to hide a widget] --> B{Should it keep layout space?}
    B -->|no, remove entirely| C[Conditional: if / ternary]
    B -->|no, but stay in tree| D[Offstage]
    B -->|yes, keep space| E[Visibility maintainSize / Opacity]
    style C fill:#1e1b4b,color:#fff

Approach 1: Conditional Rendering (most common)

Just include the widget only when needed. With setState toggling a flag:

bool _showDetails = false;

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      ElevatedButton(
        onPressed: () => setState(() => _showDetails = !_showDetails),
        child: Text(_showDetails ? "Hide" : "Show"),
      ),
      if (_showDetails) Text("Here are the details!"),   // collection-if
    ],
  );
}

The if inside a children list (collection-if) cleanly adds/removes the widget - when hidden, it's not in the tree at all and takes no space. A ternary works too:

_showDetails ? DetailsWidget() : const SizedBox.shrink(),

SizedBox.shrink() is a zero-size placeholder for the "nothing" branch.

Approach 2: Visibility Widget

Visibility toggles without restructuring your tree, and can optionally preserve layout space:

Visibility(
  visible: _showDetails,
  child: Text("Details"),
  // optional:
  // maintainSize: true, maintainAnimation: true, maintainState: true,
)

Approach 3: Offstage

Offstage keeps the widget in the tree and builds it, but doesn't paint it or give it size:

Offstage(
  offstage: !_showDetails,
  child: ExpensiveWidget(),
)

Useful when you want to keep the widget's state alive and ready (e.g. measure it, or toggle quickly) without showing it.

Approach 4: Opacity (visible space, transparent)

Opacity(opacity: 0.0, child: ...) renders the widget and reserves its space but makes it transparent. It still receives layout and (unless wrapped) can still be interactive, so it's the right tool only when you specifically want "invisible but present." Note it's relatively expensive to animate.

Choosing the Right One

Need Use
Remove completely, free its space if / ternary, or Visibility (default)
Keep its space (avoid layout shift) Visibility(maintainSize: true) or Opacity
Keep built & stateful but not shown Offstage
Animate the appearance AnimatedOpacity / AnimatedSwitcher

Animated Show/Hide

For smooth transitions:

AnimatedOpacity(
  opacity: _showDetails ? 1.0 : 0.0,
  duration: const Duration(milliseconds: 300),
  child: Text("Details"),
)

AnimatedSwitcher cross-fades between two widgets when the child changes.

Why This Matters in Interviews

Flutter interviews use this to test understanding of the widget tree and the layout-vs-paint distinction. The key insight: hiding isn't one thing - if/ternary removes the widget entirely, Visibility can keep or drop its space, Offstage keeps it built but unpainted, Opacity keeps space but transparent. Knowing that conditional construction is cheapest (the widget simply isn't there) and that setState drives the toggle is the core.

Common Pitfalls

References

More answers