Simple Recipes App made in Flutter — Detail View and Settings Widget
Today it is about getting more comfortable in creating and playing with Flutter widgets.
In previous articles of this series, we have learned how to develop the user interface of the login page and the list view. Furthermore, we have learned how to add our project to Firebase and implement Google Sign-In for our application. In the last article, we have discovered how to use Firestore in order to save our recipes in a cloud database. This time we are going to implement a detail view for our recipes and a widget that we are going to use for the settings view.
During the last weeks, I have noticed how important it is to be confident in the usage of Flutter widgets. More comfortable you feel in doing it more effectively you can work on the implementation of your applications. This applies all the more if we are using Dart and Flutter, because of the simplicity and flexibility that they offer us. I hope you can get more confidence in the implementation of custom Flutter widgets by following this article and possibly you can learn something new. Let us take a look at the further implementation of the simple recipes app made in Flutter. We are going to start with the detail view.
We are going to see more information about a recipe in the detail view. The detail view is going to consist of a header, tabs containing ingredients and preparation steps and a floating button that enables us to add a recipe to our favorites or to delete it by using Firestore. We are going to stick to Material Design guidelines and implement a simple and clean user interface.
Firstly, let’s create widgets
RecipeTitle. We’re going to use them in the already existing widget
RecipeCard and in the detail view that we are going to implement afterwards. We are going to implement these widgets because the way how we show images and titles of our recipes is going to be pretty much the same in two widgets. We want to make this way reusable and do not repeat the code.
Add the code that follows to a new file lib/ui/widgets/recipe_image.dart.
RecipeImage is a simple StatelessWidget that gets passed an URL of a recipe image. This widget returns an image wrapped by an AspectRatio widget that applies an aspect ratio of 16:9 to the image.
Let’s move to the next widget. You can see the implementation of the widget
RecipeTitle below. The widget
RecipeTitle awaits arguments recipe and padding. The
build method of
RecipeTitle contains mostly the code of the already existing method
_buildTitleSection in lib/ui/widgets/recipe_card.dart. It returns the title section that we can see in our recipe card widgets.
Before we get hands on the implementation of the detail view let’s change
RecipeCard in lib/ui/widgets/recipe_card.dart and use
RecipeTitle. Delete the method
_buildTitleSection and change the
build method as you can see below. Don’t forget to import the new widgets.
Let’s try it out and see where we can find the widgets that
RecipeTitle consists of. You can execute flutter run on the command line to start the app. If the app is already running press ‘r’ to perform a hot reload on the command line or click on the hot reload button in your IDE to quickly reload the app. If you are using Android Studio or IntelliJ IDEA I can only recommend you to take a look at the widget inspector. It is a great tool for analyzing custom Flutter widgets and understanding the layouts. You can find more information about the widget inspector and how to get started with it here. Now let’s see what the inspector tells us about our widget
It seems to be what we have expected after implementing our brand new widget
RecipeTitle. Don’t hesitate to play with the widget inspector for a better understanding of our widget layout.
Great. Now, let’s implement the detail screen.
We want our detail screen contains a header that looks similar to the widget
RecipeCard, a pinned tab bar including tabs for ingredients and preparation steps and scrollable views with the content.
First, create a new file detail.dart in lib/ui/screens/ and add a new StatefulWidget
DetailScreen. It’s going to await a
Recipe object and a boolean
inFavorites. We are going to use the Flutter widget NestedScrollView for the implementation.
Here is the description of
NestedScrollView from the Flutter documentation:
A scrolling view inside of which can be nested other scrolling views, with their scroll positions being intrinsically linked.
Notice how we create a new TabController on the initialization of
TabController makes the TabBar and TabBarView work together. Furthermore, we initialize a ScrollController object in the method
ScrollController object is going to be used to control the position the outer scroll view is scrolled to in the NestedScrollView.
Here is the implementation of the detail screen:
Now create widgets
PreparationView that we are going to use in the tab bar view. Both of them are wrapped by the padding of 75.0 in the bottom, because of the floating button in the detail screen. We want to prevent that the floating button overlaps the content of tab bar view in case the content is very long and we scroll down the view. In other words, we do not want that the button blocks an area of the content.
You can see the expected result below. The floating button does not prevent us from reading the whole content in the inner view of our detail screen.
Put the code that follows into lib/ui/screens/detail.dart.
Now, we are going to use
DetailScreen in the widget
RecipeCard. We are going to navigate users to the detail screen on tap on a
As the next step, we are going to add styles for the tab bar to our theme in lib/ui/theme.dart.
Well done! We have just finished implementing the detail view. Let’s take a look at the implementation of the settings widget.
For the time being, we are going to implement a settings view which contains a single button to sign out a user of Google and Firebase. Feel free to extend the view by adding more of
SettingsButton widgets that we are going to implement in this part of this article.
As the first step, we are going to extend the state widget.
Add the method
_StateWidgetState. In this method, we are going to sign out the user of Firebase and Google. Afterwards, we are going to create a new state object in setState.
Here is the code:
HomeScreen widget is going to rerender and build a login screen because of none Firebase user is set:
As next, we are going to implement a reusable button for the settings view. The settings button is going to await an icon, a title, a caption and a function callback as positional arguments.
Here is the implementation:
We are going to implement the settings view as the method
HomeScreenState. The method
_buildSettings is going to return a column containing a settings button.
Let’s take a look at the implementation:
In order to build the settings view we need to extend the method
HomeScreenState and use
Today we have learned how to:
- create custom reusable widgets
- use the widget inspector to analyze the widget layout
- use NestedScrollView in order to implement a view containing an outer header and an inner view
- sign out a user of Google and Firebase
I hope that you could learn something new or get more confidence in creating custom Flutter widgets.
This article is the last of the series about the recipes app. Thank you for following this series. Initially, the idea for this series was to write articles about the implementation of an app that I have finished before starting to write the first article. I reviewed the code before writing each article and every time I could do something better. I’ve learned a lot by writing these blog posts.
You can expect more articles about Flutter in the near future.
I wish you happy fluttering!