Search code examples
flutterdartexceptionandroid-snackbar

How can I fix exception "Floating SnackBar presented off screen" in flutter


I have an app that displays a snackbar when some action is done. I had tested this with my phone and some emulator and it works. Recently I installed an emulator with android 13 and maybe a bigger resolution and I'm getting this error:

The following assertion was thrown during performLayout():
Floating SnackBar presented off screen.

A SnackBar with behavior property set to SnackBarBehavior.floating is fully or partially off screen because some or all the widgets provided to Scaffold.floatingActionButton, Scaffold.persistentFooterButtons and Scaffold.bottomNavigationBar take up too much vertical space.

Consider constraining the size of these widgets to allow room for the SnackBar to be visible.

The relevant error-causing widget was
Scaffold
dashboard.dart:69
When the exception was thrown, this was the stack
#0      _ScaffoldLayout.performLayout.<anonymous closure>
#0      _ScaffoldLayout.performLayout.<anonymous closure>
scaffold.dart:1189
#1      _ScaffoldLayout.performLayout
scaffold.dart:1204
#2      MultiChildLayoutDelegate._callPerformLayout
custom_layout.dart:240
#3      RenderCustomMultiChildLayoutBox.performLayout
custom_layout.dart:410
#4      RenderObject._layoutWithoutResize
object.dart:2027
#5      PipelineOwner.flushLayout
object.dart:1020
#6      RendererBinding.drawFrame
binding.dart:516
#7      WidgetsBinding.drawFrame
binding.dart:865
#8      RendererBinding._handlePersistentFrameCallback
binding.dart:381
#9      SchedulerBinding._invokeFrameCallback
binding.dart:1289
#10     SchedulerBinding.handleDrawFrame
binding.dart:1218
#11     SchedulerBinding._handleDrawFrame
binding.dart:1076
#12     _invoke (dart:ui/hooks.dart:145:13)
#13     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:338:5)
#14     _drawFrame (dart:ui/hooks.dart:112:31)
The following RenderObject was being processed when the exception was fired: RenderCustomMultiChildLayoutBox#3f6d8 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
RenderObject: RenderCustomMultiChildLayoutBox#3f6d8 NEEDS-LAYOUT NEEDS-COMPOSITING-BITS-UPDATE
    needs compositing
    parentData: <none> (can use size)
    constraints: BoxConstraints(w=411.4, h=867.4)
    size: Size(411.4, 867.4)
    child 1: RenderRepaintBoundary#ba78b relayoutBoundary=up1
        needs compositing

I have no idea how can I debug what is going on here. The code works in smaller devices/older versions of android. The popups are triggered quiet straightforward:

SnackBar getSnackbar({
  required String message,
  required Color backgroundColor,
}) {
  return SnackBar(
    elevation: 8,
    backgroundColor: backgroundColor,
    behavior: SnackBarBehavior.floating,
    content: Row(children: [
      Flexible(
        child: Text(
          message,
          style: const TextStyle(
            color: Colors.white,
          ),
        ),
      )
    ]),
    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
  );
}

ScaffoldMessenger.of(context)
 ..hideCurrentSnackBar()
 ..showSnackBar(getSnackbar(
 backgroundColor: Colors.green,
 message: 'File saved to $filename',
 ));

The screen where this is called does not have any Scaffold.floatingActionButton, Scaffold.persistentFooterButtons and Scaffold.bottomNavigationBar as the exception says. It is just a Scaffold with a body:


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('SomeScreen'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: _isLoading
            ? const Center(child: CircularProgressIndicator())
            : Column(children: [
                _displaySomething(),
                Expanded(
                    child: Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    _displayAnotherThing(),
                  ],
                ))
              ]),
      ),
    );
  }

Update: I have futher debugged the issue and it also happens in older versions of android. So it may be related to a recent update of flutter but I'm not able to find why. I was able to see the problem appears only with behavior:SnackBarBehavior.floating,.

Also removing all the code from the Scaffolfd, leaving just the TextButton that triggers the snackbar is enough to reproduce the issue, but I don't know what can I do with it.


Solution

  • I cross posted this here, because I though it was a bug. But there it was explained that for the SnackBars you have to also consider other Scaffolds in the widget tree as moving backwards would keep the snackbar "flying" and could collide with elements of the previous Scaffolds.

    So as a summary on how to solve this issue, take a look not only in the screen where you see the exception triggered but also from previous screens.