15 November 2021

Building Cross-Platform apps with PlatformBuilder

A dive into how the PlatformBuilder widget has helped us design cross-platform widgets.

Dan Reynolds
Dan Reynolds @thederivative

When working with cross-platform apps, it is often valuable to share widgets like inputs, cards, lists and other core components across platforms like web and native. To make building these cross platform widgets easier, we created Platform Builder, a Flutter library for performing platform checks and building widgets by platform.

Platform checks

The library includes a Platform singleton that you can use check to the current platform anywhere in the app:

import 'package:platform_builder/platform_builder.dart';

if (Platform.instance.isAndroid) {
  print('android');
} else if (Platform.instance.isWeb) {
  print('web');
}

These checks are based on the dart:io Platform class and expand it to support additional platforms, including a built-in check for web and chrome extensions.

Platform builders

You can always make platform checks in your build functions, but we found using a dedicated PlatformBuilder widget made things easier. The widget will throw an error if we accidentally miss specifying a platform we support and organizes all of our checks in a consistent way.

import 'package:platform_builder/platform_builder.dart';

class MyWidget extends StatelessWidget {
  @override
  build(context) {
    return PlatformBuilder(
      androidBuilder: (context) => Icon(Icons.android),
      iOSBuilder: (context) => Icon(Icons.apple),
    ),
  }
}

Platforms

The libray provides builders for the following platforms:

  • android
  • iOS
  • macOS
  • linux
  • fuschia
  • windows
  • web
  • chrome extension

By default all platforms are enabled and the PlatformBuilder will throw an error if you forget to include an implementation for one of the supported platforms. To specify your preferred platforms, call the Platform.init to initialize the Platform singleton with the list of your application’s supported platforms:

import 'package:platform_builder/platform_builder.dart';

Platform.init(
  supportedPlatforms: [
    Platforms.iOS,
    Platforms.android,
    Platforms.web,
  ]
);

If a particular PlatformBuilder needs to override the global list of supported platforms, such as during active development, you can pass an override to the widget:

import 'package:platform_builder/platform_builder.dart';

class MyWidget extends StatelessWidget {
  @override
  build(context) {
    return PlatformBuilder(
      supportedPlatforms: [Platforms.iOS, Platforms.android],
      androidBuilder: (context) => Icon(Icons.android),
      iOSBuilder: (context) => Icon(Icons.apple),
    ),
  }
}

Builder precedence

The precedence of builders is based on specificity. More specific builders take precedence over broader ones as shown below:

import 'package:platform_builder/platform_builder.dart';

class MyWidget extends StatelessWidget {
  @override
  build(context) {
    return PlatformBuilder(
      builder: (context) {...},
      nativeBuilder: (context) {...},
      androidBuilder: (context) {...},
    ),
  }
}

In this example on a web platform, all three builders are applicable, but the precedence would be:

  • androidBuilder
  • nativeBuilder
  • builder

Tell us what you need

Something missing? Let us know what additional platform utilities would be helpful for your workflow.

Categories

Flutter Library