Recreating Fruta, the WWDC2020 app with Flutter

Jonathan Thomas
6 min readJan 23, 2021
Photo by freestocks on Unsplash

There are already several articles online that can explain just what Flutter is and how it has taken over the cross-app development world.

The focus of this article is to explore the extent to which one might be able to recreate an iOS based app within the concerns of Flutter and what better way than to use the Fruta demo app from WWDC 2020 built with SwiftUI, another up and coming declarative framework. Similar work has been done by the team at Very Good Ventures who went over the Landmarks Swift UI app in Flutter and you can check out their blog post here.

In this project, the emphasis is to use only the Cupertino widgets library and not use the Material library in any file that is user-interface based. Although that being the case, if there was need to achieve a number of effects or functionalities in the app, packages or plugins where need be were introduced and there is a likelihood that they could have been built with Material components and as such I have no control over them.

With all that said and done…let’s get to the code.

There is a somewhat heavy reliance on the SwiftUI project which provided the smoothie data as well as the image assets used in the project. Furthermore, most measurements and color codes for individual components were attained through reading into the code files.

Preparing Assets

The Xcode project already comes with all the assets so it was just a matter of copying over the files into their respective folders.It was long hard work organising the smoothie_data.json file but I got it done. You are free to take advantage of my hard work for your own benefit. 😜

Create the project and set up your main file as follows.

Main file with Cupertino navigation set up

Using the CupertinoTabScaffold, we are able to set up our main navigation for the application and assign each screen to a CupertinoTabView.

A little heads-up, if you want to have your text react properly to dark mode(which Flutter gives us automatically out of the box), it is important you add the basic textTheme: CupertinoTextThemeData(), to your CupertinoThemeData. This will allow Flutter to auto-magically assign the right text color contrast for light and dark themes.

The great thing is that Flutter automatically handles a number of platform adaptations on our behalf depending on the platform the application is running on. Therefore, it is great to know that everything from page navigation handling to back-handling & typography are handled for me out of the box. You can read more on this from the Platform Adaptations resources section on the Flutter website.

Menu List Screen

Flutter(left) — Native iOS(right)

Smoothie Details Screen

This was by far the most complicated screen to work on given a number of different aspects of the screen as well as the complex parsing needed to get the ingredients cards to work as similarly as the native SwiftUI app.

Flutter Smoothie Details screen

However, let me draw out two main feature points and both relate to the ingredient grid widget.

Firstly, the grid element container for the ingredients is a stack with the image. The most text uses a simple blendMode of BlendMode.softlight to give that semi-transparent see-through look.

The next is that when the grid item is tapped, it opens up into a CupertinoPopupSurface that houses the flip_card that showcases the ingredient at the front face of the card and at the rear, the nutritional information related to the ingredient.

Favourites Screen

A simple screen to keep track of any smoothies you have liked. For the simple task of adding to favourites and persisting across app restarts, I made use of the hive, a simple, lightweight and fast key-value database.

Flutter Favourites Screen with CupertinoBottomModal for quick details

The code below will both be able to add and remove from favourites as well as update the icon according to the state of the smoothie.

On the favourites screen, Flutter provides a functional class, ValueListenableBuilder, that will automatically refresh the UI based on the data stored in hive. In this case we wish to have the screen update automatically each time we add or remove a smoothie from the favorites list.

Rewards Screen

This was a fun screen to build and also quite simple to build with the help of the animated_background package to animate the screen background.

Flutter Rewards(left) — Native Rewards(right)

Recipes Screen

Flutter Recipes(left) — Native Recipes(right)

Dark Mode 🌙

As mentioned earlier with Flutter you can get support for dark mode easily out of the box. Just as long as you maintain and keep all widgets used as Cupertino then using the system wide flip is just easy.

FlutterFruta Dark Mode Screens

Conclusion

Taking everything into consideration, this was a fun project to explore the depths to which developing an iOS application with Flutter with the likeness of a native app can be done. It is safe to say that to an extent Flutter wildly exceeds expectations and with more in the pipeline to bring about a number of near native features, I can say the future is promising for Flutter in the iOS design space.

For the app-size nerds out there, building the app, in profile mode, with the help of GitHub actions was able to output an artifact at just 82.4MB.In release mode, the artifact was at 240MB.

I will hope to be covering a Part 2 and Part 3 that will see me attempt to add two very complex features that were introduced in iOS14; home widgets and app clips.

Home Widgets provide a window into features of an application. It is great that the Flutter community has already began work to bring this functionality to Flutter applications as covered by the following GitHub issue #60026 and community packages, home_widget and flutter_widgetkit.

App Clips are lightweight versions of the main application that provide quick access to features or tasks provided by your application and are accessible by scanning a visual code or NFC. Flutter at present has experimental support for adding App clips to your app that isn’t production ready.

You can check out the full code for the app over at the repository on my Github profile. I invite any suggestions for improvement both here and on the repository.

Till then, Happy coding. 💙

--

--