Flutter: Use Platform Widgets to Adopt Native Look and Feel

Marco Muccinelli
Level Up Coding
Published in
4 min readJun 10, 2020

--

I’m not too convinced that cross-platform UI will ever be a real thing in terms of final product quality (btw, I think a real thing might be Kotlin Multiplatform logic + native UI layer), nobody can doubt that tools like Flutter or React Native are really effective if we talk about quick prototyping and deployment.

Flutter, in particular, helps a lot to deliver a good looking Material Design app with a few lines of code. But a Material app is not and will never be a real iOS app, so you need to use Cupertino widgets duplicating a lot of the code. Wouldn’t it be great if there were a package to use adaptive widgets?

Platform Widgets

That package exists, and it is flutter_platform_widgets. You can install it easily inside pubspec.yaml file:

The main building block is PlatformWidget, which is a widget that is aware of the target platform look and feel.

Platform Widget package exposes many useful adaptive widgets, everything is listed inside project’s read me.

Migrate Material app to adaptive app

Let’s start with a typical Material app with a drawer and some contents below the app bar.

As you can see, this is not the correct look for iOS. Let’s use adaptive widgets inside the content.

Et voilà! Do you want a larger spinner? No problem:

Let’s try to give a more natural appearance also to the app bar.

Development tip: it might be useful to enclose PlatformApp inside a PlatformProvider widget in order to be able to force the platform in different environments via initialPlatform property.

As you can see we have lost the drawer in iOS. That’s because CupertinoApp does not support it, so PlatformScaffold must be instructed to keep using it in the Material environment. This is correct since the hamburger menu anti-pattern is discouraged by Apple. Instead, you would like to have a tab bar.

And… nothing happens! Platform Widget package ignored this attribute. Apparently it does so on purpose:

This library aims to provide a similar interface between ios and android.
https://github.com/stryder-dev/flutter_platform_widgets/issues/72#issuecomment-531204229

Use different paradigms

So we have to use PlatformWidget directly to achieve the desired result.

MaterialLayout is a small stateless widget to encapsulate Material layout:

Please note that I’m not defining an app bar here, delegating to the real page laid out inside AppContent widget. This widget would grow in complexity if I handled drawer selections.

TabbedLayout is a bit more complex since defines the tab bar for Cupertino paradigm:

Please note the usage of platform-specific icons and that every tab describes an isolated navigator, which preserves the navigation stack even when user switches between tabs.

AppContent widget now outputs a PlatformScaffold with common parts of the UI:

Navigate to a second screen

Navigation is supported out of the box. You have just to use platformPageRoute() in Navigator.push() invocation:

Details is a simple stateless widget that builds a PlatformScaffold:

Theming

You can also specify different app-level themes:

Then you can adjust some specific colors, deeper in the hierarchy. For example, disabled tab color is not readable:

--

--