The Scaffold widget implements the basic Material Design visual layout for your app. As such, it provides a means for showing drawers, snack bars, and bottom sheets. As of this writing, it’s involved in implementing, six elements defined in the Material Design: The AppBar class, the FloatingActionButton class, the Drawer class, the BottomNavigationBar class, the SnackBar class, and last but not least, the BottomSheet class.
Above is a snapshot of the sample app found on the webpage, Scaffold class. As with all my articles, you can tap/click on the screenshots to get to its source. In this one sample, there are no less than five named parameters utilized from the Scaffold widget. Three of which depicts elements defined in the Material Design guidelines. Those being the AppBar, the BottomNavigationBar and the FloatingActionButton.
Traditionally, what I do is go through a widget’s many named parameters, describing their use, in turn, in the attempt to demonstrate the widget itself as a whole. I’ll do the same here supplying appropriate examples and sample code for each when possible.
I Like Screenshots. Click For Gists.
As always, I prefer using screenshots over gists to show concepts rather than just show code in my articles. I find them easier to work with frankly. However, you can click or tap on these screenshots to see the code they represent in a gist or in Github. Ironically, it’s better to read this article about mobile development on your computer than on your phone. Besides, we program on our computers — not on our phones. For now.
No Moving Pictures On Social Media
Note, there are a number of gif files in this article demonstrating functions and features with ‘moving pictures.’ However, I’m told viewing such files is not possible when reading this article on platforms like Instagram, Facebook, etc. You’ll see empty square spaces where the gif files should be. I wanted you to be aware of this, and recommend reading this on medium.com.
The App’s Toolbar
The first one we’ll look at is the named parameter, appBar. It’s the toolbar running along the ‘top’ of the screen typically seen in mobile apps.
The AppBar class is responsible for implementing this prominent feature for your Flutter app. There’s a lot involved in such a class. Above is an extensive example utilizing practically all of the AppBar widget’s own parameters. Go to its gist by clicking on it and take it aside for further review if you like.
The Body of Your App
The main ‘body’ or your app would be represented by the widget passed to the Scaffold’s parameter, body. In the screenshot above, you see I’ve placed a red border around the body of the Scaffold. Conceivably, you could have any number of widgets within the body of the Scaffold. It’s ‘the guts’ of your app.
Where the Action is
In many app’s you’ll see a button seemingly floating above the body of the app usually in the lower right-hand corner. In many cases, it’s a round button with a plus sign in the middle used to add new items into your app. For example, every time you create a ‘New Flutter Project’, the sample code includes a Scaffold widget with its own FloatingActionButton widget. See below.
And so, the next parameter we’re looking at is the floatingActionButton parameter. Again, such a button is part of the Material Design guidelines and so is readily available to the Scaffold widget as its own parameter.
Above is a screenshot implementing other aspects of the FloatingActionButton widget involving mostly its shape and general appearance. Tap/click on the screenshot to see an associated gist containing the source code.
Any Widget Will Do
So, at the parameter, floatingActionButton, the Scaffold widget typically takes in a widget of the class, FloatingActionButton. However, do note the parameter is of type, Widget. That means it could conceivably take in any widget. Even one displaying a ‘smiley’ face as seen above.
Location! Location! Location!
The next parameter found in the Scaffold widget is called, floatingActionButtonLocation. A rather descriptive name for a parameter responsible for the ‘location’ of the aforementioned FloatingActionButton. Below are screenshots depicting this parameter taking in all the locations currently available to you.
If this parameter is not specified the default location for the button is the first one depicted, FloatingActionButtonLocation.endFloat. There are seven options to choose from and easily distinguishable from each other in the screenshots above. Note, the sixth one, miniStartTop, listed above is a little smaller in size than the others.
That’s because, as seen in that screenshot above, and described in the documentation, “…so that the floating action button appears to align with CircleAvatars in the ListTile.leading slot of a ListTile in a ListView in the Scaffold.body.”
Our next parameter is called, persistentFooterButtons. It takes in a List of Widgets. And in most cases, it’s a list of FlatButton widgets. FlatButton are yet another element described in Material Design. Below is an example of introducing seven buttons using the parameter, persistentFooterButtons.
Not Too Persistent
Note, if a text field is introduced to the sample code above allowing for then a keyboard to appear, the persistently visible bar of buttons is not so much of either. Something to keep in mind.
Draws a Drawer
In the screenshot above, not one but two additional parameters from the Scaffold widget are introduced, the drawer and the endDrawer parameters. Traditionally, the endDrawer is revealed on the screen by swiping your finger from right-to-left; the drawer comes about by swiping your finger from left-to-right.
Further, as you see in the gif file displayed above, if the AppBar detects a Drawer is available from the Scaffold widget, it displays the ‘menu’ IconButton in its front end or its back end depending on the parameter used. The Scaffold itself that handles the edge-swipe gestures needed to show the drawers.
What’s Your Type?
A specific parameter of the BottomNavigationBar widget called, type, is involved in a number of attributes pertaining to the BottomNavigationBar and its items. Below are screenshots of but a few locations in Flutter’s source code, bottom_navigation_bar.dart, involving the ‘type’ parameter.
Everything from the size to the colour of the items listed along the bottom navigation bar is dictated by the BottomNavigationBarType.
For example, as you see above, if the type is ‘shifting’ and there’s at least one BottomNavigationBarItem with a specified background colour then that colour will override the BottomNaviagationBar’s own background colour and fill in the whole area. This would not be the case if type was instead ‘fixed.’
The App Bar at the Bottom
BottomAppBar widget was introduced as an additional component to the Material Design at the Google I/O conference in 2018. It’s seen as an extension of the Toolbar situated at the top of mobile apps, with this extension instead located at the bottom.
In the screenshot above, the BottomAppBar widget takes in a Row widget that, in this case, includes a ‘menu’ icon and a ‘search’ icon enclosed in an IconButton’s. The BottomAppBar widget allows for a visual ‘notch’ wrapping it a little bit around the floating action button.
Flutter: BottomAppBar Navigation with FAB
Today we’ll see how to add a FloatingActionButton (FAB) with options to a BottomAppBar in Flutter. And we'll build this…
Take The Bottom Sheet
In the documentation, it’s said to supplement the content displayed in the body of the Scaffold widget. Passing a widget to the parameter, bottomSheet, makes what is called a ‘persistent bottom sheet.’ It’s there for good now until you pass Null or remove the widget from that very same parameter.
Put All Together
In the screenshot above, I’ve combined all the elements we’ve reviewed so far. You can see at a glance, where those components we’ve reviewed so far relate to each other in placement.
What’s The Primary Reason?
Let’s continue going along now and talk about the named parameter, primary. By default, this boolean property is set to true. However, setting it to false, then you’ll notice a reduced thickness of the toolbar (the AppBar).
In the sample code above, not one, not two, but three Scaffold’s are in play here — each with their own AppBar. Note, the skinny AppBar displayed in the gif above is caused by the named parameter, primary, set to false.
You can see where in the Scaffold’s State object where the extra padding comes about if the primary property is set to true.
Adjusting For Keyboard
The next two named parameters we’ll look at are resizeToAvoidBottomPadding and resizeToAvoidBottomInset. Both involve resizing the Scaffold’s contents when the keyboard appears. In fact, the second one is to replace the first one. resizeToAvoidBottomPadding has been deprecated and is literally replaced by resizeToAvoidBottomInset.
With the help of hot reload, the gif above depicts the consequences of setting resizeToAvoidBottomPadding from false, to true, and back to false again. When you see the line of text, ‘This line goes behind the keyboard. Click here and see’, the parameter is set to true. When it goes behind the keyboard, that parameter is set to false.
The property, resizeToAvoidBottomInset, would induce the same behaviour. In fact, it overrides any setting of the property, resizeToAvoidBottomPadding, as the latter is now depreciated and to be replaced by the former property.
Where’s the SnackBar?
The interface element, SnackBar, is also described in Material Design. It’s to convey a brief message at the bottom of the app’s screen describing what may have just happened. For example, the gif file below notifies the user has just deleted an item — and even provides a means to ‘undo’ the deletion.
The screenshot above introduces a RaisedButton to the sample code. When pressed, a SnackBar object is instantiated, and the Scaffold’s State object calls the method, showSnackBar(), to display the message.
Under What Context?
Notice in the screenshot of the sample code above, a Builder widget was introduced to allow for the successful retrieval the Scaffold’s State object of type, ScaffoldState — done using the static function, Scaffold.of(). Without it, the call would have resulted in the following error message:
“Scaffold.of() called with a context that does not contain a Scaffold”
You see, the context object has to come from a ‘child’ widget of the Scaffold and not be the context from the very widget that instantiated the Scaffold. And so, supplying this intervening widget, Builder, as a child widget will then produce a context object that contains a reference to the Scaffold widget.
An Alternate Key
Alternatively, another approach is the use of a GlobalKey to acquire a reference to the Scaffold’s State object. The key is passed to the Scaffold’s constructor and later used to reference its State object.
In the screenshot above, there is now no need for the intervening ‘child’ widget as the Scaffold’s State object is retrieved by other means.
The State of the Scaffold
The Scaffold’s State object is of class type, ScaffoldState. Indeed it retains and conveys the state of the Scaffold object. The screenshot below of the ScaffoldState class reveals the number of getters it contains to tell you about its Scaffold’s current state.
State Your Scaffold’s State
Below is the previous sample code now inundated with memory variables attaining values from the Scaffold’s State object many getter’s. The results of which are then displayed in lines of text underneath the RaisedButton.
You’ll note that a lot of the values are set to false. Stands to reason, as most of them pertain to the Drawer where none is implemented…yet.
Open Your Drawer or Your Sheet
With the Scaffold’s State object, you can also perform some actions. Within code, you are able, for example, to open the drawer and or bottomsheet if included in the Scaffold object. The sample code will now allow for just that.
The screenshot shows the code that opens the Scaffold’s bottom sheet announcing which Drawer was opened at a given moment. It’s either the left-hand drawer or the right-hand drawer. The Scaffold’s State object’s showBottomSheet() function is called upon to do just that.
*Source code as of May 29, 2019
^Source code as of May 15, 2019