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.

Photo by Samuel Yongbo Kwon on Unsplash

Introduction

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.

Detail View

Final Result

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.

Initial Steps

Firstly, let’s create widgets RecipeImage and 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.

lib/ui/widgets/recipe_image.dart

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.

lib/ui/widgets/recipe_title.dart

Before we get hands on the implementation of the detail view let’s change RecipeCard in lib/ui/widgets/recipe_card.dart and use RecipeImage and RecipeTitle. Delete the method _buildTitleSection and change the build method as you can see below. Don’t forget to import the new widgets.

lib/ui/widgets/recipe_card.dart

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 RecipeTitle.

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.

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 _DetailScreenState. A TabController makes the TabBar and TabBarView work together. Furthermore, we initialize a ScrollController object in the method initState. The 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:

lib/ui/screens/detail.dart

Now create widgets IngredientsView and 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.

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 RecipeCard widget.

lib/ui/screens/detail.dart

Theme

As the next step, we are going to add styles for the tab bar to our theme in lib/ui/theme.dart.

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.

Settings Widget

Final Resul

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.

State Widget

As the first step, we are going to extend the state widget.

Add the method signOutOfGoogle to _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:

lib/state_widget.dart

After calling setState the HomeScreen widget is going to rerender and build a login screen because of none Firebase user is set:

lib/ui/screens/home.dart

Settings Button

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:

lib/ui/widgets/settings_button.dart

Settings View

We are going to implement the settings view as the method _buildSettings in HomeScreenState. The method _buildSettings is going to return a column containing a settings button.

Let’s take a look at the implementation:

lib/ui/screens/home.dart

In order to build the settings view we need to extend the method _buildTabsContent in HomeScreenState and use _buildSettings:

lib/ui/screens/home.dart

Conclusion

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!