Understanding the Issue

When building multi-step forms in Flutter using the Stepper widget, you might encounter a rendering glitch where calling showTimePicker (or showDatePicker) renders the picker dialog behind the stepper layout. As a result, the dialog becomes unclickable, unresponsive, and fails to dismiss when switching steps.

Why Does This Happen?

This behavior is caused by context and navigator overlay hierarchies in Flutter. By default, showTimePicker attempts to look up the nearest Navigator in the widget tree using the provided BuildContext. If your Stepper or step content operates inside a nested navigator or custom overlay stack, the picker dialog gets rendered inside that local sub-tree layer instead of the global application screen overlay.

The Fix: Use useRootNavigator: true

The simplest and most effective solution is to explicitly instruct showTimePicker to use the root navigator. Setting useRootNavigator: true pushes the modal dialog onto the top-most overlay layer, placing it squarely in front of the Stepper widget and all other UI elements.

Updated Code Solution

Modify your ElevatedButton's onPressed handler by adding useRootNavigator: true to the showTimePicker call:

ElevatedButton(
  child: const Text("Choose Time"),
  onPressed: () async {
    final TimeOfDay? timeOfDay = await showTimePicker(
      context: context,
      initialTime: selectedTime,
      initialEntryMode: TimePickerEntryMode.dial,
      useRootNavigator: true, // Fixes z-index layering issues
    );
    if (timeOfDay != null) {
      setState(() {
        selectedTime = timeOfDay;
      });
    }
  },
)

Additional Troubleshooting Tips

  • Date Pickers: If you face the same layer issue with showDatePicker, pass useRootNavigator: true there as well.
  • Valid Context: Ensure that the context passed to the picker function is valid and actively mounted. Wrapping your step content inside a Builder widget can help if you still experience context lookup issues.