adaptive_library 0.7.0 icon indicating copy to clipboard operation
adaptive_library: ^0.7.0 copied to clipboard

A set of Widgets that create a native look and feel on iOS and Android.

Adaptive Library #

Important note #

This project is no longer maintained. Recently it was updated to support the latest Dart 2.17 and Flutter 3, but from now on, there is no longer any maintenance. You should definitely check out any other package that support platform-agnostic widgets!

The package #

A set of widgets that create a native look and feel on iOS and Android.

Flutter already gives us a great library for Material and Cupertino widgets. But as a cross platform tool, Flutter does not provide a good way of displaying the right widget design types on each platform dynamically.

adaptive_library crashes in and... here it is!

Note: this version supports null safety. You need to be on the flutter beta channel. Go to this article to learn more about it.

Getting Started #

To get started, import the package to your app, after getting the package.

import 'package:adaptive_library/adaptive_library.dart';

The widgets #

Our library currently contains 9 widgets that can be used to create a native look and feel on iOS and Android devices. There are more in the future, so stay tuned.

Most of the time, you can replace the base class name of a widget with the ones from this library. You do not need to rename or remove parameters; though at some points you eventually need to add one parameter (This makes adaptive_library great, huh?)

Important things in advance #

adaptive_library uses the concept of InheritedWidget to get access to the current platform. This makes sure that you do not need to reenter Platform.isAndroid || Platform.isIOS or whatever, every time you need a widget. And yes, "Fluttering" is done by widgets, so this would be... nah. ;)

AdaptiveInheritance #

AdaptiveInheritance is the core class. Every adaptive widget needs it, because it defines the Platform "state" (-> Android or iOS).

      adaptiveState: AdaptiveState.Cupertino,
      child: AdaptiveApp(

Typically, AdaptiveInheritance is the parent of the whole app. It enabled the functionality to reload all the widgets that are based on Platform state at the same time.

adaptiveState is set by an enum containing the fields; and if you want to set it dynamically, simply call AdaptiveInheritance.getStateByPlatform(). This method uses Dart's io package to find out which Platform the app is currently running on, providing the correct AdaptiveState.

In this example, the direct child is AdaptiveApp, that combines MaterialApp and CupertinoApp.

AdaptiveApp #

        home: HomeScreenPage(),

Use this to enable Material or Cupertino design for your app. Like the "originals", you can set parameters like debugShowCheckedModeBanner and home to define your app. The full list of parameters are growing, and can be inspected in the class.


materialTheme and cupertinoTheme is used to apply the correct themeData to your app.

AdaptiveScaffold #

This is a cool thing.

      title: Text('Tests Page'),
      body: Text('Your content'),
      actions: []

This is a replacement for Scaffold and CupertinoScaffold and combines them both. The title is set in the AppBar (CupertinoNavigationBar) and also, actions can be provided via actions field.

Notice that some fields, like drawer and floatingActionButton have no effect on Cupertino design.

On Cupertino, the default CupertinoNavigationBar is used. To get one with large title, simply


This has no effect on Material style.

Custom AppBar (CupertinoNavigationBar)

If you want to have you app bar customized, set either the appBar or cupertinoNavigationBar property on AdaptiveScaffold.


You can of course assign a key to the Scaffolds, to show a SnackBar for example. The field is scaffoldKey.

AdaptiveButton #

    child: Text('Your child'),
    onPressed: () => null,

As you can see, you can simply replace FlatButton, CupertinoButton or other buttons by AdaptiveButton. No need to change parameters.

You can specify a color for Material button style, but it is recommended to set via the theme in AdaptiveApp.


The code, by default, creates a FlatButton or CupertinoButton respectively. To use raised or filled version, append .raised like so:


AdaptiveIconButton #

          icon: Icon(Icons.check_circle_outline),
          iconCupertino: Icon(CupertinoIcons.check_mark_circled),
          onPressed: () => null,

Flutter currently has no Cupertino equivalent to IconButton, so AdaptiveIconButton makes it. Provide either an icon to use it on both designs, or define another icon for Cupertino, because CupertinoIcons look a bit different.

Here, you can also replace IconButton by AdaptiveIconButton without extra work

AdaptiveAlertDialog #

To use a platform based alert dialog, it is recommended to use instead of using it as a widget.<String>(
              adaptiveState: AdaptiveInheritance.getStateByPlatform(),
              title: Text('Hallo'),
              content: Text('Einfach mal Hallo sagen'),
              actions: [],

Unlike the other widgets, you need to set the AdaptiveState manually right now. (We're working on this).

show uses a generic parameter that lets you specify the data you want to return.

Notice: Using closeOnPress with AdaptiveAlertDialogButton, the dialog is dismissed without any parameter. To get the result of a dialog, go like the normal way and specify it inside the ActionButtons. See next section for more info.

The actions

Because iOS devices do not have the typical "back" button by default, it is recommended to provide actions to dismiss the dialog. If you really do not want to use action buttons, set an empty array.

Define actions

actions: [
                child: Text('OK'),
                destructive: true,
                onPressed: () {
                    //do stuff here
                closeOnPress: true,
                child: Text('Thanks'),
                onPressed: null,

AdaptiveAlertDialogButton decides whether to use a FlatButton or a CupertinoDialogAction. You can leave out onPressed or set it to null; by setting closeOnPress to true, the dialog is dismissed, regardless of onPressed being set. In case closeOnPress is set to true, there will be no "return" value passed with Navigator.pop

Setting destructive enables the typically red colored button that indicates a "destructive/cancel" action in Cupertino styled dialogs.

AdaptiveProgressIndicator #

AdaptiveProgressIndicator(value: 45)            

Either displays a CircularProgressIndicator or a CupertinoActivityIndicator. value is ignored on Cupertino style.

AdaptiveListTile #

              title: Text('Brightness'),
              subtitle: Text('Change brightness'),
              onTap: () {
                //do stuff here.

On Cupertino, there is a little grey row with borders, like the typical settings entry known from iOS. leading, trailing and dense will not work on Cupertino.

What else? #

There are more widgets coming up in the future, so keep track!

I have an idea #

Great. Pull requests are very welcome!

pub points


unverified uploader

A set of Widgets that create a native look and feel on iOS and Android.



API reference


Icon for licenses.Apache-2.0 (LICENSE)




Packages that depend on adaptive_library