Sunday, July 15, 2018

Flutter: Showing SnackBar within the Widget that builds a Scaffold


Sometimes you need to implement a simple logic that shows SnackBar. Let's imagine there is a Button that shows a SnackBar.


After pushing the Button you can see the following error:

"Scaffold.of() called with a context that does not contain a Scaffold. No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This usually happens when the context provided is from the same StatefulWidget as that whose build function actually creates the Scaffold widget being sought..."

Scaffold.of() called with a context that does not contain a Scaffold. No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This usually happens when the context provided is from the same StatefulWidget as that whose build function actually creates the Scaffold widget being sought. There are several ways to avoid this problem. The simplest is to use a Builder to get a context that is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of(): https://docs.flutter.io/flutter/material/Scaffold/of.html A more efficient solution is to split your build function into several widgets. This introduces a new context from which you can obtain the Scaffold. In this solution, you would have an outer widget that creates the Scaffold populated by instances of your new inner widgets, and then in these inner widgets you would use Scaffold.of(). A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function.

It happens because the current context doesn't contain a Scaffold. Even though we see that our build function returns Scaffold. Context starts to look for a Scaffold in the parent and the current build function is dismissed.

Let's implement all suggested techniques to fix the problem (from the screenshot above).

Builder Widget


We start by wrapping the Button with a Builder Widget. It is a platonic Widget that calls a closure to obtain its child widget. To display the SnackBar it uses a context from Builder.


Split a build function


The next suggested approach is to split a build function into several widgets. That's why we move our Button to a StatelessWidget.


The build function has a child context and our SnackBar displays successfully.

Global Key


The last recommended approach is to assign a GlobalKey to the Scaffold. A key that is unique across the entire app. Global keys uniquely identify elements, provide access to other objects that are associated with elements, such as a BuildContext and, for StatefulWidgets, a State. Global keys are expensive, and, in my opinion, it is not a good approach to solve this problem if there are another two approaches that are described above.  But anyway let's have a look at how to implement this. We need to create a Global key instance and assign it to the Scaffold Widget:

After that we will get a state of the Scaffold to show the SnackBar:

Resources:

No comments:

Post a Comment