Skip to content
Lance Johnstone edited this page Apr 14, 2023 · 5 revisions

Installation

pub.dev: https://pub.dev/packages/flutter_platform_widgets/install

How it works

Instead of having to write conditional code like this...

if (Platform.isAndroid) {
  return ElevatedButton(onPressed: onPressed, child: child);
} else if (Platform.isIOS) {
  return CupertinoButton.filled(onPressed: onPressed, child: child);
}

you can use a single platform widget which will render the correct underlying widget based on the ThemeData.platform property...

return PlatformElevatedButton(onPressed: onPressed, child: child);

The heavy lifting of choosing the right widget is done for you.

You can also specify what design language you want for any supported platforms within flutter. These include:

  • Android
  • iOS
  • Web
  • Macos
  • Windows
  • Linux

Getting started

To make the most out of a single PlatformWidget it is best to replace the MaterialApp with the PlatformApp and to add the PlatformProvider widget above it. Although strictly both are not required, some platform specific widgets may expect them to be present. from v3.3 onwards a PlatformTheme widget can be added between PlatformProvider and PlatformApp to control the light and dark themes of both the material and cupertino style independently of each other.

Replace the MaterialApp with the following...

PlatformProvider(
  builder: (context) => 
    PlatformTheme(
      builder: (context) => PlatformApp(
        localizationsDelegates: <LocalizationsDelegate<dynamic>>[
          DefaultMaterialLocalizations.delegate,
          DefaultWidgetsLocalizations.delegate,
          DefaultCupertinoLocalizations.delegate,
        ],
        title: 'Flutter Platform Widgets',
        home: _YourHomePage_(),
     ),
  ),
)

Note: setting localizationsDelegates property is recommended since localizations are not by default used within Cupertino, particularly if you mix and match material and cupertino widgets within your application.

Properties on PlatformProvider widget include...

Property Description
initialPlatform A platform override value from TargetPlatform or null to default to the device's platform
settings An instance of type PlatformSettingsData which can control what platform gets what design language widgets
builder (required) The main builder function which typically has the PlatformApp or PlatformTheme as its child

Notable properties on the PlatformApp widget include...

Property Description
PlatformApp.router Named constructor which configures the underlying MaterialAp.router or CupertinoApp.router widgets

PlatformProvider settings

There are a number of settings that you can set that applies to the entire application when you add PlatformProvider above the main PlatformApp widget. To have additional settings, just add it to settings of the provider.

PlatformProvider(
  settings: PlatformSettingsData(...),
  builder: ...
)

Properties

iosUsesMaterialWidgets

If you plan to use a mixture of Material and Cupertino widgets within your app and use PlatformApp for iOS then you need to set the following

This is because material widgets expect a Scaffold or Material parent widget which by default is not added when using the cupertino widgets.

platformStyle

By default the style of an android application will take the material style, and an apple application will take the cupertino style. You can change what style the target platform will have by setting the platformStyle property.

The following are the defaults used.

Platform Style
android Material
windows Material
web Material
fushia Material
linux Material
ios Cupertino
macos Cupertino

iosUseZeroPaddingForAppbarPlatformIcon

From v2.1 you can ensure that for a PlatformIconButton added to the cupertino app bar have zero padding which is required to visually align properly on the app bar. This zero padding is ignored if the PlatformIconButton already has a padding added to it.

legacyIosUsesMaterialWidgets

Not recommended to set, however exists for older projects that want to ensure a Material as a parent. Prefer setting iosUsesMaterialWidgets

wrapCupertinoAppBarMiddleWithMediaQuery

package version >=3.2.0

Controls whether the CupertinoNavigationBar middle property is wrapped with a MediaQuery as defined in this flutter issue: https://github.com/flutter/flutter/issues/42759#issuecomment-591087271. This has a default value of true which will change the behaviour of the from version 3.1.0 of the package. If the behaviour is not required then set this property to false

Extended properties

Each platform widget has the list of properties shared between material and cupertino within the platform constructor itself, in the same way the default flutter widgets are made. However not all properties are common between the two. So in this case you can further customise the platform widget specifically for the target platform.

Take the PlatformTextButton widget as an example:

return PlatformElevatedButton(
  onPressed: onPressed, 
  child: const Text('Click Me!'),
);

Here the onPressed and child properties are common between material and cupertino so they are provided directly on the PlatformTextButton constructor. However what is being used for material is the TextButton widget and for cupertino it is the CupertinoButton widget. If you want to change or handle something specific for the target platform widget you need to extend it by doing this...

return PlatformElevatedButton(
  onPressed: onPressed, 
  child: const Text('Click Me!'),
  material: (_, __) => MaterialTextButtonData(
    autofocus: true,
  ),
  cupertino: (_, __) => CupertinoTextButtonData(
    disabledColor: Colors.white
  ),
);

The (_, __) builder arguments are BuildContext and PlatformTarget which you can use explicitly if you need to use the context or need to know about the platform that is being targeted.

To get the full list of possible extended properties for each platform widget it is best to look at the source code itself as the amount of properties some of the widgets have is just too much to list.