Target the specific design of Material for Android and Cupertino for iOS widgets through a common set of Platform aware widgets

Overview

Flutter Platform Widgets

Flutter Platform Widgets

Pub GitHub

This project is an attempt to see if it is possible to create widgets that are platform aware. Currently in order to render targeted Material or Cupertino device specific styles, you need to either conditionally check the platform or create a set of widgets to render differently depending on the running platform.

This package supports the Stable release as a full released version.

Beta or Dev channels might be supported when there is a pre-release version. Please check the CHANGELOG for version compatibility version.

Due to Master being in rapid development this package is unable to support Master. If this support is required then it is best to fork the repo and locally reference the forked version where changes can be made appropriately.

Installation

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

How it works

The flutter ThemeData object used with the Theme widget has a platform property. This defaults to TargetPlatform.android on Android and TargetPlatform.ios on iOS (also for macos etc), but when creating a ThemeData object, it can be set programmatically. Calling Theme.of(context).platform will return the current platform. Several Flutter library widgets use this field to change how they are rendered, and all of the Flutter Platform Widgets library widgets use this field to render the platform specific versions of things.

Configuration

See PlatformProvider for configuration options.

Widgets

These set of widgets allow for rendering based on the target platform using a single cross platform set of widget.

alt text

alt text

Each PlatformWidget provides common properties directly as constructor arguments. If required further customization can be achieved by using the platform widget builder. See the Enhance section of each widget.

PlatformWidget

A widget that will render either the material widget or cupertino widget based on the target platform. The widgets themselves do not need to be specifically Material or Cupertino.

return PlatformWidget(
  cupertino: (_, __) => Icon(CupertinoIcons.flag),
  material: (_, __)  => Icon(Icons.flag),
);

PlatformText

A widget that will render uppercase for material. Cupertino will remain unchanged.

return PlatformText('Cancel');

PlatformSwitch

A switch widget that will use a Switch for material or a CupertinoSwitch for cupertino.

return PlatformSwitch(
  onChanged: (bool value) {},
  value: value,
);

Enhance

return PlatformSwitch(
  onChanged: (bool value) {},
  value: value,
  material: (_, __)  => MaterialSwitchData(...),
  cupertino: (_, __) => CupertinoSwitchData(...)
);

PlatformSlider

A slider widget that will use a Slider for material or a CupertinoSlider for cupertino

return PlatformSlider(
  onChanged: (bool value) {},
  value: value,
);

Enhance

return PlatformSlider(
  onChanged: (bool value) {},
  value: value,
  material: (_, __)  => MaterialSliderData(...),
  cupertino: (_, __) => CupertinoSliderData(...)
);

PlatformTextField

A text field widget that will use a TextField for material or a CupertinoTextField for cupertino.

return PlatformTextField();

Enhance

return PlatformTextField(
  material: (_, __)  => MaterialTextFieldData(...),
  cupertino: (_, __) => CupertinoTextFieldData(...)
);

PlatformButton

A button that will render a RaisedButton or FlatButton for material or a CupertinoButton for cupertino.

return PlatformButton(
  onPressed: () => print('send'),
  child: PlatformText('Send'),
);

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformButton(
  onPressed: () => print('send'),
  child: PlatformText('Send'),
  material: (_, __)  => MaterialRaisedButtonData(...),
  cupertino: (_, __) => CupertinoButtonData(...)
);

Note: For material you can use the FlatButton instead. To do this use the MaterialFlatButtonData on the materialFlat argument.

Note: For cupertino you can use the CupertinoButton.filled instead. To do this use the CupertinoFilledButtonData on the cupertinoFilled argument.

return PlatformButton(
 onPressed: () => print('send'),
 child: PlatformText('Send'),
 materialFlat: (_, __)    => MaterialFlatButtonData(),
 cupertinoFilled: (_, __) => CupertinoFilledButtonData(),
);

PlatformIconButton

A clickable (tappable) button with an icon. Uses IconButton for material or CupertinoButton for cupertino.

return PlatformIconButton(
  onPressed: () => print('info pressed'),
  materialIcon: Icon(Icons.info),
  cupertinoIcon: Icon(
    CupertinoIcons.info,
    size: 28.0,
  ),
);

Enhance

Extend with PlatformBuilder for material or cupertino.

Widget infoIconButton() {
  return PlatformIconButton(
    onPressed: () => print('info pressed'),
    materialIcon: Icon(Icons.info),
    cupertinoIcon: Icon(CupertinoIcons.info),
    material: (_, __)  => MaterialIconButtonData(...),
    cupertino: (_, __) => CupertinoIconButtonData(...),
  );
}

PlatformApp

A top level widget for the application that uses MaterialApp for material or CupertinoApp for cupertino.

return PlatformApp(
  title: 'Flutter Demo',
  home: ...
);

or

return PlatformApp.router(
  routeInformationParser: ...
  routerDelegate: ...
)

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformApp(
  home:  ...
  material: (_, __)  => MaterialAppData(...)
  cupertino: (_, __) => CupertinoAppData(...)
);

or

return PlatformApp.router(
  material: (_, __)  => MaterialAppRouterData(...)
  cupertino: (_, __) => CupertinoAppRouterData(...)
);

PlatformScaffold

A Scaffold that provides the correctly hosted header (AppBar) and navigation bar (Bottom Bar) for each platform. Uses Scaffold for material or CupertinoTabScaffold for cupertino with bottom tabs or CupertinoPageScaffold for cupertino without bottom tabs.

return PlatformScaffold(
  appBar: PlatformAppBar()
  body: _buildContent(),
  bottomNavBar: PlatformNavBar(),
  iosContentPadding: false,
  iosContentBottomPadding: false
);

Note that the use of iosContentPadding = true is only required if the content is being obstructed behind the appBar. iosContentBottomPadding is used if the content needs to be above the navBar and not go behind it. This will not have the translucent effect for iOS when these are set to true. If that is desirable, then the scrolling and content alignment need to be managed yourself.

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformScaffold(
  appBar: PlatformAppBar()
  body: _buildContent(),
  bottomNavBar: PlatformNavBar(),
  material: (_, __)  => MaterialScaffoldData(...)
  cupertino: (_, __) => CupertinoPageScaffoldData(...);
);

Both the material and cupertino builders are optional. If not provided the Container placeholder widget will be returned.

PlatformTabScaffold

Note: Using PlatformTabScaffold provides a more refined and flexible experience than using PlatformScaffold.

A Scaffold that provides the correctly hosted header (AppBar) and navigation bar (Bottom Bar) for each platform. Uses Scaffold for material or CupertinoTabScaffold for cupertino with bottom tabs.

return PlatformTabScaffold(
  tabController: tabController,
  appBarBuilder: (_, index) => PlatformAppBar(),
  bodyBuilder: (context, index) => _buildContent(index),
  items: _items(context),
);

More more detailed example look at:

Note that the use of iosContentPadding = true is only required if the content is being obstructed behind the appBar. iosContentBottomPadding is used if the content needs to be above the navBar and not go behind it. This will not have the translucent effect for iOS when these are set to true. If that is desirable, then the scrolling and content alignment need to be managed yourself.

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformTabScaffold(
  tabController: tabController,
  appBarBuilder: (_, index) => PlatformAppBar(),
  bodyBuilder: (context, index) => _buildContent(index),
  items: _items(context),
  material: (_, __)  => MaterialTabScaffoldData(...)
  cupertino: (_, __) => CupertinoTabScaffoldData(...);
  materialtabs: (_, __) => MaterialNavBarData(...)
  cupertinoTabs: (_, __) => CupertinoTabBarData(...);
);

Both the material and cupertino builders are optional. If not provided the SizedBox.shrink() placeholder widget will be returned. material can be replaced with materialBuilder for dynamic rendering on index change cupertino can be replaced with cupertinoBuilder for dynamic rendering on index change

PlatformAppBar

The AppBar is the top Header bar with a title, left-side or right-side buttons. Uses AppBar for material or CupertinoNavigationBar for cupertino.

return PlatformAppBar(
    title: new Text('Platform Widgets'),
    leading: PlatformIconButton(),
    trailingActions: <Widget>[
      PlatformIconButton(),
    ],
  );

In Cupertino if a solid color header is required and there is a ListView on the page, you would need to add some alpha to the color so that the ListView is not pushed down too far

     appBar: PlatformAppBar(
       title: Text('iOS Colored Header'),
       cupertino: (_, __) => CupertinoNavigationBarData(
             // Issue with cupertino where a bar with no transparency
             // will push the list down. Adding some alpha value fixes it (in a hacky way)
             backgroundColor: Colors.lightGreen.withAlpha(254),
           ),
     ),

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformAppBar(
  title: new Text('Platform Widgets'),
  leading: PlatformIconButton(),
  trailingActions: <Widget>[
    PlatformIconButton(),
  ],
  material: (_, __)  => MaterialAppBarData(...),
  cupertino: (_, __) => CupertinoNavigationBarData(...),
);

PlatformNavBar

The NavBar is placed at the bottom of the page with a set of buttons that typically navigate between screens. Implementing this widget requires the parent widget to manage the currentIndex of the page and to set PlatformNavBar.currrentIndex. Uses BottomAppBar with BottomNavigationBar for material or CupertinoTabBar for cupertino.

return PlatformNavBar(
  currentIndex: _selectedTabIndex,
  itemChanged: (index) => setState(
        () {
          _selectedTabIndex = index;
        },
      ),
  items: [
    BottomNavigationBarItem(),
    BottomNavigationBarItem(),
  ],
);

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformNavBar(
  currentIndex: _selectedTabIndex,
  itemChanged: (index) => setState(
        () {
          _selectedTabIndex = index;
        },
      ),
  items: [
    BottomNavigationBarItem(),
    BottomNavigationBarItem(),
  ],
  material: (_, __)  => MaterialNavBarData(...),
  cupertino: (_, __) => CupertinoTabBarData(...),
);

PlatformPopupMenu

The PlatformPopupMenu will render a using a PopupMenuButton for material or use a CupertinoActionSheet for cupertino which will display a list of actions.

return PlatformPopupMenu(
  options: [
    PopupMenuOption(label: 'One', onTap: _navToPageOne),
    PopupMenuOption(label: 'Two', onTap: _navToPageTwo),
    PopupMenuOption(label: 'Three', onTap: _navToPageThree)
  ],
  icon: Icon(
    context.platformIcon(
      material: Icons.more_vert_rounded,
      cupertino: CupertinoIcons.ellipsis,
    ),
  ),
);

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformPopupMenu(
  options: [
    PopupMenuOption(label: 'One', onTap: _navToPageOne),
    PopupMenuOption(label: 'Two', onTap: _navToPageTwo),
    PopupMenuOption(label: 'Three', onTap: _navToPageThree)
  ],
  icon: Icon(
    context.platformIcon(
      material: Icons.more_vert_rounded,
      cupertino: CupertinoIcons.ellipsis,
    ),
  ),
  material: (_, __)  => MaterialPopupMenuData(...),
  cupertino: (_, __) => CupertinoPopupMenuData(...),
);

PlatformAlertDialog

The AlertDialog will render a caption/title, body/text and a set of action buttons specific for the platform. Uses AlertDialog for material or CupertinoAlertDialog for cupertino.

Note use showPlatformDialog instead of either showDialog from the Material library or showCupertinoDialog from the Cupertino library.

alt text

alt text

showPlatformDialog(
  context: context,
  builder: (_) => PlatformAlertDialog(
    title: Text('Alert'),
    content: Text('Some content'),
    actions: <Widget>[
      PlatformDialogAction(),
      PlatformDialogAction(),
    ],
  ),
);

Enhance

Extend with PlatformBuilder for material or cupertino.

showDialog(
  context: context,
  builder: (_) => PlatformAlertDialog(...),
  cupertino: (_, __) => CupertinoAlertDialogData(...),
  material: (_, __)  => MaterialAlertDialogData(...),
)

PlatformDialogAction

The DialogAction widget is used to describe the set of buttons on the AlertDialog. Uses TextButton for material or CupertinoDialogAction for cupertino. If you want to use FlatButton for material which is the default pre v1.9.0 then set legacyMaterialDialogActionButtons setting on PlatformProvider

PlatformDialogAction(
  child: PlatformText('Cancel'),
  onPressed: () => Navigator.pop(context),
),

Enhance

Extend with PlatformBuilder for material or cupertino.

PlatformDialogAction(
  child: PlatformText('Cancel'),
  onPressed: () => Navigator.pop(context),
  material: (_, __)  => MaterialDialogActionData(...),
  cupertino: (_, __) => CupertinoDialogActionData(...),
),

PlatformCircularProgressIndicator

A circular looking progress indicator. Uses CircularProgressIndicator for material or CupertinoActivityIndicator for cupertino.

return PlatformCircularProgressIndicator();

Enhance

Extend with PlatformBuilder for material or cupertino.

return PlatformCircularProgressIndicator(
  material: (_, __)  => MaterialProgressIndicatorData(...),
  cupertino: (_, __) => CupertinoProgressIndicatorData(...),
);

PlatformPageRoute

This function can be used within the Navigator to push either the MaterialPageRoute for material or CupertinoPageRoute for cupertino.

  Navigator.push(
    context,
    platformPageRoute(
      context: context,
      builder: pageToDisplayBuilder,
    ),
  );

Enhance

Extend with PlatformBuilder for material or cupertino.

return platformPageRoute(
  context: context,
  material: (_, __)  => MaterialPageRouteData(...),
  cupertino: (_, __) => CupertinoPageRouteData(...),
);

PlatformPage

This function can be used within flutter's Navigator 2 to push either the MaterialPage for material or CupertinoPage for cupertino.

    platformPage(
      context: context,
      child: child,
    ),
  );

Enhance

Extend with PlatformBuilder for material or cupertino.

return platformPage(
  context: context,
  material: (_, __)  => MaterialPageData(...),
  cupertino: (_, __) => CupertinoPageData(...),
);

ShowPlatformModalSheet

This function is used to either display a ModalBottomSheet for material or CupertinoModalPopup for cupertino.

  showPlatformModalSheet(
      context: context,
      builder: (_) => PlatformWidget(
        material: (_, __)  => _materialPopupContent(),
        cupertino: (_, __) => _cupertinoSheetContent(),
      ),
    );

Note: Since Material and Cupertino content may be quite different it may be useful to use PlatformWidget.

ShowPlatformDatePicker

This function is used to either display a DatePickerDialog for material or CupertinoDatePicker via a showCupertinoModalPopup for cupertino.

  showPlatformDatePicker(
      context: context,
      initialDate: DateTime.now(),
      firstDate: DateTime.now().subtract(const Duration(days: 1000)),
      lastDate: DateTime.now().add(const Duration(days: 1000)),
    );

Note: The Cupertino popup uses a modal bottom sheet. If you need to customize the look then set the cupertinoContentBuilder property and return a custom content. If you create your own content builder you will need to manage the state of the date yourself. See the implementation of using StatefulBuilder or StatefulWidget to manage state updates within the example project.

final date = await showPlatformDatePicker(
    context: context,
    firstDate: DateTime.now().subtract(const Duration(days: 100)),
    lastDate: DateTime.now().add(const Duration(days: 100)),
    initialDate: DateTime.now(),
    cupertinoContentBuilder: (contentData, data) =>
        _CustomCupertinoDatePicker(contentData: contentData),
  );

PlatformProvider

A Provider that provides access to the functions of switching platforms which can be accessed from any screen.

Requires to be placed at the root (above MaterialApp, CupertinoApp or PlatformApp).

  return PlatformProvider(
    builder: (BuildContext context) => MaterialApp(...)
  );

Arguments

initialPlatform

An optional argument initialPlatform can be passed in to force the platform upon startup. This could be useful for development or if the platform is persisted externally (i.e. Shared preferences) and needs to be set on startup.

And to switch platforms...

PlatformProvider.of(context).changeToMaterialPlatform();

or

PlatformProvider.of(context).changeToCupertinoPlatform();

or

PlatformProvider.of(context).changeToPlatform(Platform.fuchsia);

This will set the Theme.of(context).platform but the platform widgets will use the style as defined in the PlatformStyle as set inside the settings object. See below.

settings

The settings argument have been added to assist in configuring Platform Widgets.

iosUsesMaterialWidgets

  • If true it will add a Material widget above the CupertinoPageScaffold so that Material widgets can be added to the ios page. This does affect dark mode and some ios rendering so it is best to have it false (default). If you use Material widgets on the page simply add Material(child: yourWidget).

platformStyle

  • Provides a way to set either Material or Cupertino style on any supported platforms such as android, ios, web, macos, fuchsia, windows amd linux. For example if you wanted to use Cupertino widgets for web you would configure by setting the settings object on PlatformProvider:
PlatformProvider(
  settings: PlatformSettingsData(
    platformStyle: PlatformStyleData(web: PlatformStyle.Cupertino)
  ),
  builder: (context) => PlatformApp(...)
)

legacyIosUsesMaterialWidgets

  • If true will have the Material widget above CupertinoScaffold and CupertinoTabScaffold rather than one level down. Having set to false will likely prevent an exception when using a material widget for a cupertino style. This setting was the default pre v1.6.0

legacyMaterialDialogActionButtons

  • If true all material dialog action buttons will use FlatButton which is the default pre v1.9.0. As of v1.9.0 the material dialog action button will use the newer material TextButton

PlatformThemeData

Helper function to a Material or Cupertino theme data property based on the platform

Text(
  platform.text,
  textAlign: TextAlign.center,
  style: platformThemeData(
    context,
    material: (data) => data.textTheme.headline5,
    cupertino: (data) => data.textTheme.navTitleTextStyle,
  ),
)

PlatformIcons

Render a Material or Cupertino looking icon

  Icon(context.platformIcons.book)
//or
  Icon(PlatformIcons(context).book)

View the source or screenshots for the list of icons.

PlatformWidgetBuilder

Renders a parent widget for either Cupertino or Material while sharing a common child Widget

 PlatformWidgetBuilder(;
   cupertino: (_, child, __) => GestureDetector(child: child, onTap: _handleTap),
   material: (_, child, __) => IniWell(child: child, onTap: _handleTap),
   child: Container(child: Text('Common text')),
 );

TODO

  • UI / Unit Tests.
  • Code documentation

Changing / Checking Platform

When importing flutter_platform_widgets you can check isMaterial(context) or isCupertino(context) to determine what style will be used. This is independent to Platform.isAndroid or Platform.isIOS from 'import 'dart:io'

You can call platform(context) to get the current platform. This is an enhancement on the existing TargetPlatform enum which now includes a value for web.

See the example code for how this is used.

Issues and Feedback

Please create an issue to provide feedback or an issue.

Contributors

Special thanks for everyone that have contributed to this project...

Lance Johnstone
Stefan Rusek
Mark Lavercombe
Fred Grott
Felizia Bernutz
eyecreate
Adrian
Eric Martineau
Gilles Montyne
Ivan Kryak
Morris Haid
Joscha Eckert
Furkan Tektas
benzel
Christian Mengler
Ben Hagen
anticafe
Nnaemeka Abah
Ezeoke Onyekachi Samuel
Jasper Koning
AlexIver
in74mz
Daniel Felten
Hans Kokx

Acknowledgements

Inspired by the example given by Swav Kulinski (https://github.com/swavkulinski/flutter-platform-specific-widgets)

Comments
  • PlatformIconButton on PlatformAppBar placed too low on iOS

    PlatformIconButton on PlatformAppBar placed too low on iOS

    PlatformIconButton on PlatformAppBar is placed too low on iOS it seem. If i change it to a IconButton, it seem correct (but does not work on iOS in some cases).

    Example:

    class MenuPage extends StatelessWidget {
      MenuPage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return PlatformScaffold(
          appBar: PlatformAppBar(
            leading: PlatformIconButton(
              icon: Icon(PlatformIcons(context).clear),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ),
          body: SafeArea(
            child: MenuContent(),
          ),
        );
      }
    }
    
    opened by erf 15
  • CupertinoTheme based on Device Brightness?

    CupertinoTheme based on Device Brightness?

    Is there a way to display light/dark mode based on the Devices brightness in iOS? I tried this:

    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
    
        final materialLightTheme = ThemeData(
          primaryColor: Colors.blueAccent,
          brightness: Brightness.light,
          scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.light),
          appBarTheme: AppBarTheme(
            color: MyColors.backgroundColor1(Brightness.light)
          ),
        );
    
    
        final materialDarkTheme = ThemeData(
          primaryColor: Colors.blueAccent,
          brightness: Brightness.dark,
          scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.dark),
          appBarTheme: AppBarTheme(
            color: MyColors.backgroundColor1(Brightness.dark)
          ),
        );
    
        final cupertinoTheme = new CupertinoThemeData(
          primaryColor: Colors.blueAccent,
          scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.light),
          barBackgroundColor: MyColors.backgroundColor1(Brightness.light)
        );
    
        final cupertinoThemeDark = new CupertinoThemeData(
          primaryColor: Colors.blueAccent,
          scaffoldBackgroundColor: MyColors.backgroundColor0(Brightness.dark),
          barBackgroundColor: MyColors.backgroundColor1(Brightness.dark)
        );
    
        Brightness brightness = MediaQuery.of(context).platformBrightness;
    
        return PlatformProvider(
          builder: (context) => PlatformApp(
            title: "Cali Move App",
            android: (context) {
              return MaterialAppData(
                darkTheme: materialDarkTheme,
                theme: materialDarkTheme,
                // themeMode: brightness == Brightness.light
                //   ? ThemeMode.light
                //   : ThemeMode.dark
              );
            },
            ios: (context) {
              return new CupertinoAppData(
                theme: brightness == Brightness.light
                    ? cupertinoTheme
                    : cupertinoThemeDark,
                // home: MyHomePage(),
              );
            } 
          ),
        );
      }
    }
    

    But I can't query the brightess with MediaQuery in the build method because MediaQuery.of() called with a context that does not contain a MediaQuery.

    opened by JonasJW 15
  • Navigation bar icons in wrong position on iOS

    Navigation bar icons in wrong position on iOS

    Hi! Thank you for writing this library! I have a problem with the bar button items on iOS. This code

            PlatformAppBar(
                title: Text(widget.title),
                trailingActions: <Widget>[
                  PlatformIconButton(icon: Icon(Icons.compare))
                ],
             )
    
    

    results in the icon to be displayed shifted and too small:

    image

    When using an iOS specific CupertinoNavigationBarData icon it works correctly:

              PlatformAppBar(
                title: Text(widget.title),
                trailingActions: <Widget>[
                  PlatformIconButton(icon: Icon(Icons.compare))
                ],
                ios: (_) =>
                    CupertinoNavigationBarData(
                      trailing: GestureDetector(
                        child: Icon(Icons.compare)),
                    ),
              ),
           )
    
    

    image

    However it should not be necessary to specify "ios", it should already work correctly with the PlatformIconButton, right? 🙂

    opened by dg76 12
  • getter

    getter "fullObstruction" error

    Eliass-MBP:isontic-Education elias$ flutter build ios
    Running "flutter pub get" in isontic-Education...                   0.6s
    Building com.isontic.ed for device (ios-release)...
     
    Automatically signing iOS for device deployment using specified development team in Xcode project: ZHW34NDW2Q
    Running Xcode build...                                                  
                                                       
     ├─Building Dart code...                                     7.2s
    Xcode build done.                                           16.2s
    Failed to build iOS app
    Error output from Xcode build:
    ↳
        ** BUILD FAILED **
    
    
    Xcode's output:
    ↳
        Building AOT snapshot in release mode (ios-release)...          
    
        Compiler message:
    
        ../../../../Elias/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.20.1/lib/src/platform_scaffold.dart:229:38: Error: The getter 'fullObstruction' isn't defined for
        the class 'ObstructingPreferredSizeWidget'.
    
         - 'ObstructingPreferredSizeWidget' is from 'package:flutter/src/cupertino/page_scaffold.dart' ('../../../../Elias/flutter/packages/flutter/lib/src/cupertino/page_scaffold.dart').
    
        Try correcting the name to the name of an existing getter, or defining a getter or field named 'fullObstruction'.
    
              final obstruct = navigationBar.fullObstruction == null ||
    
                                             ^^^^^^^^^^^^^^^
    
        ../../../../Elias/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.20.1/lib/src/platform_scaffold.dart:230:25: Error: The getter 'fullObstruction' isn't defined for
        the class 'ObstructingPreferredSizeWidget'.
    
         - 'ObstructingPreferredSizeWidget' is from 'package:flutter/src/cupertino/page_scaffold.dart' ('../../../../Elias/flutter/packages/flutter/lib/src/cupertino/page_scaffold.dart').
    
        Try correcting the name to the name of an existing getter, or defining a getter or field named 'fullObstruction'.
    
                  navigationBar.fullObstruction;
    
                                ^^^^^^^^^^^^^^^
    
        Compiler terminated unexpectedly.
        Failed to build /Users/elias/Documents/GitHub/isontic-Education.
        Command PhaseScriptExecution failed with a nonzero exit code
        note: Using new build systemnote: Planning buildnote: Constructing build descriptionwarning: The use of Swift 3 @objc inference in Swift 4 mode is deprecated. Please address deprecated
        @objc inference warnings, test your code with “Use of deprecated Swift 3 @objc inference” logging enabled, and then disable inference by changing the "Swift 3 @objc Inference" build
        setting to "Default" for the "Runner" target. (in target 'Runner' from project 'Runner')
    
    Encountered error while building for device.
    Eliass-MBP:isontic-Education elias$ 
    
    opened by edeuss 12
  • Error with CupertinoNavigationBar

    Error with CupertinoNavigationBar

    ../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.72.0/lib/src/platform_app_bar.dart:202:9: Error: No named parameter with the name 'actionsForegroundColor'.
            actionsForegroundColor: data?.actionsForegroundColor,
            ^^^^^^^^^^^^^^^^^^^^^^
    ../../../development/flutter/packages/flutter/lib/src/cupertino/nav_bar.dart:220:9: Context: Found this candidate, but the arguments don't match.
      const CupertinoNavigationBar({
            ^^^^^^^^^^^^^^^^^^^^^^
    ../../../development/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.72.0/lib/src/platform_app_bar.dart:222:7: Error: No named parameter with the name 'actionsForegroundColor'.
          actionsForegroundColor: data?.actionsForegroundColor,
          ^^^^^^^^^^^^^^^^^^^^^^
    ../../../development/flutter/packages/flutter/lib/src/cupertino/nav_bar.dart:220:9: Context: Found this candidate, but the arguments don't match.
      const CupertinoNavigationBar({
            ^^^^^^^^^^^^^^^^^^^^^^
    
    

    Using:

    sdk: '>=2.7.0 <3.0.0'
    flutter_platform_widgets: ^0.72.0
    
    opened by erperejildo 11
  • why initstate() is called multiple times in stateful widget when we use platform widgets?

    why initstate() is called multiple times in stateful widget when we use platform widgets?

    if we combine platform widget with PlatformNavBar,after we switch from tab1 to tab2, initstate() nitstate() is called multiple times!!! Really a big issue ! ` return PlatformNavBar( currentIndex: _selectedTabIndex,

      itemChanged: (int index) {
        setState(() {
          _selectedTabIndex = index;
        });
      },
      items: [
        BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('home')
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.search),
            title: Text('search')
        ),
        BottomNavigationBarItem(
            icon: Icon(Icons.shopping_cart),
            title: Text('shopping_cart')
        ),
    
    
      ],
    );`
    
    opened by miroda 11
  • On Ios when dark mode is enabled, text is shown dark, making text invisible

    On Ios when dark mode is enabled, text is shown dark, making text invisible

    As in the title, here a attached the default app generated by flutter and modified in order to be used with the library that exhibits the problem. With the Standard Cupertino Scaffold/App, the problem is not shown.

    main.dart.zip

    opened by andreacimino 10
  • Switch Platform Question

    Switch Platform Question

    This issue is slightly related with #21. I was recently working on a university project and decided to use platform_widgets for easier cross platform support. I decided to implement a separate settings screen and add a change platform button under dev settings. However upon implementing that every time platform was changed I was navigating back to the main screen. As I understand changeToCupertinoPlatform() should be used in the beginning of the app but is there a way to do that and have the changes propagate in the root widget once the back button in the settings screen is pressed rather than jumping directly back?

    opened by giannissc 10
  • SafeArea:top=true results in extra top padding when using solid bgColor for CupertinoNavigationBarData

    SafeArea:top=true results in extra top padding when using solid bgColor for CupertinoNavigationBarData

    Continuation from the fixed bug of https://github.com/aqwert/flutter_platform_widgets/issues/15

    If you have a SafeArea in your Scaffold body, a solid bgColor in the CupertinoNavigationBarData will still result in too much padding between the bar and the body content.

    Below is the code to show. I've set variables named solidNav and safeTop that will trigger whether or not the bar is solid colored or translucent and whether the safearea applies to the top param or not.

    import 'package:flutter/material.dart';
    import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Test(),
        );
      }
    }
    
    class Test extends StatefulWidget {
    
      Test({Key key}) :
            super(key: key);
    
      @override
      _TestState createState() => _TestState();
    }
    
    class _TestState extends State<Test> {
    
      bool solidNav = true;
      bool safeTop = true;
    
      @override
      Widget build(BuildContext context) {
    
        return PlatformScaffold(
          appBar: _buildAppBar(),
          body: _buildBody(),
        );
      }
    
      Widget _buildAppBar() {
        return PlatformAppBar(
          title: Text("test",
            style: Theme.of(context).textTheme.title.copyWith(
              color: solidNav ? Colors.white : Colors.black,
            ),
          ),
          ios: (BuildContext context) => _buildAppBariOS(),
        );
      }
    
    
      CupertinoNavigationBarData _buildAppBariOS() {
        return CupertinoNavigationBarData(
          backgroundColor: solidNav ? Colors.black : null,
        );
      }
    
      Widget _buildBody(){
        return SafeArea(
          top: safeTop,
          child: Container(
            color: Colors.grey,
            child: Center(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  RaisedButton(
                    child: Text("Solid navbar with SafeArea:top=false"),
                    onPressed: (){
                      setState(() {
                        solidNav = true;
                        safeTop = false;
                      });
                    },
                  ),
                  RaisedButton(
                    child: Text("Solid navbar with SafeArea:top=true"),
                    onPressed: (){
                      setState(() {
                        solidNav = true;
                        safeTop = true;
                      });
                    },
                  ),
                  RaisedButton(
                    child: Text("Translucent navbar with SafeArea:top=true"),
                    onPressed: (){
                      setState(() {
                        solidNav = false;
                        safeTop = true;
                      });
                    },
                  ),
                ],
              ),
            ),
          ),
        );
      }
    
    
    }
    
    
    
    

    0000

    opened by aaronfg 8
  • Using GetX?

    Using GetX?

    Is there somewhere a documentation on how to use the PlatFormWidgets with GetX? Currently struggling with the PlatformTabScaffold and the tabController :(

    opened by Urkman 7
  • Not working with last flutter stable version: Flutter 1.20.0 • channel stable

    Not working with last flutter stable version: Flutter 1.20.0 • channel stable

    Hi I created a project from scratch and added the package to my pubspec.yaml. The project it's outputting this errors.

    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:67:23: Error: Type 'ActionFactory' not found.
      final Map<LocalKey, ActionFactory> actions;
                          ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:96:21: Error: Type 'ActionFactory' not found.
          Map<LocalKey, ActionFactory> actions,
                        ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:152:21: Error: Type 'ActionFactory' not found.
          Map<LocalKey, ActionFactory> actions,
                        ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:219:23: Error: Type 'ActionFactory' not found.
      final Map<LocalKey, ActionFactory> actions;
                          ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:67:23: Error: 'ActionFactory' isn't a type.
      final Map<LocalKey, ActionFactory> actions;
                          ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:96:21: Error: 'ActionFactory' isn't a type.
          Map<LocalKey, ActionFactory> actions,
                        ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:152:21: Error: 'ActionFactory' isn't a type.
          Map<LocalKey, ActionFactory> actions,
                        ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:219:23: Error: 'ActionFactory' isn't a type.
      final Map<LocalKey, ActionFactory> actions;
                          ^^^^^^^^^^^^^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:312:30: Error: The argument type 'Map<LocalKey, invalid-type>' can't be assigned to the parameter type 'Map<Type, Action<Intent>>'.
     - 'Map' is from 'dart:core'.
     - 'LocalKey' is from 'package:flutter/src/foundation/key.dart' ('../flutter/packages/flutter/lib/src/foundation/key.dart').
     - 'Type' is from 'dart:core'.
     - 'Action' is from 'package:flutter/src/widgets/actions.dart' ('../flutter/packages/flutter/lib/src/widgets/actions.dart').
     - 'Intent' is from 'package:flutter/src/widgets/actions.dart' ('../flutter/packages/flutter/lib/src/widgets/actions.dart').
          actions: data?.actions ?? actions,
                                 ^
    ../../../.pub-cache/hosted/pub.dartlang.org/flutter_platform_widgets-0.51.0/lib/src/platform_app.dart:363:30: Error: The argument type 'Map<LocalKey, invalid-type>' can't be assigned to the parameter type 'Map<Type, Action<Intent>>'.
     - 'Map' is from 'dart:core'.
     - 'LocalKey' is from 'package:flutter/src/foundation/key.dart' ('../flutter/packages/flutter/lib/src/foundation/key.dart').
     - 'Type' is from 'dart:core'.
     - 'Action' is from 'package:flutter/src/widgets/actions.dart' ('../flutter/packages/flutter/lib/src/widgets/actions.dart').
     - 'Intent' is from 'package:flutter/src/widgets/actions.dart' ('../flutter/packages/flutter/lib/src/widgets/actions.dart').
          actions: data?.actions ?? actions,
                                 ^
    

    The current flutter version that I'm using.

    Flutter 1.20.0 • channel stable • https://github.com/flutter/flutter.git
    Framework • revision 840c9205b3 (13 hours ago) • 2020-08-04 20:55:12 -0700
    Engine • revision c8e3b94853
    Tools • Dart 2.9.0
    

    Thanks!

    opened by hazzo 7
  • Reopen: appbar trailing widget off center #44

    Reopen: appbar trailing widget off center #44

    Reopening the old issue https://github.com/stryder-dev/flutter_platform_widgets/issues/44

    Trailing actions on ios appBar are not vertically centered.

    Using flutter 3.3.6 and flutter_platform_widgets: ^2.0.0

        return PlatformIconButton(
          icon: const Icon(Icons.settings_outlined),
          // padding: EdgeInsets.zero,
    
    image

    As advised in https://github.com/stryder-dev/flutter_platform_widgets/issues/44 , setting the button padding to zero works, but I feel like this should be centered out of the box.

    opened by tmaihoff 0
  • PlatformNavBar wrong index on swipe back in iOS

    PlatformNavBar wrong index on swipe back in iOS

    I have a PlatformNavBarthat when I swipe back (back button) to the previous view, in the bottom bar the tab's icon is colored on the right tab, but the tab's label is wrong. This happens only on iOS and not on Android, so this make me think it could be a bug. So, for instance, I have a situation where I have the Tab 1 icon colored but the label disabled and the Tab 3 icon disabled but the label colored.

    This is how I create the PlatformNavBarobject:

    PlatformNavBar getPlatformNavBar(BuildContext context, int currentIndex, Function(int) onItemChanged) {
    
      const double iconSize = 24;
    
      return PlatformNavBar(
        backgroundColor: Colors.blue,
        currentIndex: currentIndex,
        itemChanged: (newIndex) async {
          onItemChanged(newIndex);
          await _onItemTapped(context, newIndex);
        },
        material: (_, __) => MaterialNavBarData(
          type: BottomNavigationBarType.fixed,
          selectedItemColor: Colors.white,
          unselectedItemColor: textDisabledColor,
        ),
        cupertino: (_, __) => CupertinoTabBarData(
          activeColor: Colors.white,
          inactiveColor: textDisabledColor,
        ),
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Container(
              width: iconSize,
              height: iconSize,
              child: SvgPicture.asset("image1", color: getIconColor(context, currentIndex, 0)),
            ),
            label: "Tab1",
          ),
          BottomNavigationBarItem(
            icon: Container(
              width: iconSize,
              height: iconSize,
              child: SvgPicture.asset("image2", color: getIconColor(context, currentIndex, 1)),
            ),
            label: "Tab2",
          ),
          BottomNavigationBarItem(
              icon: Container(
                width: iconSize,
                height: iconSize,
                child: SvgPicture.asset("image3", color: getIconColor(context, currentIndex, 2)),
              ),
              label: "Tab3",
          ),
          BottomNavigationBarItem(
            icon: Container(
              width: iconSize,
              height: iconSize,
              child: SvgPicture.asset("image4", color: getIconColor(context, currentIndex, 3)),
            ),
            label: "Tab4",
          )
        ],
      );
    }
    
    Color getIconColor(BuildContext context, int currentIndex, int iconIndex) {
      if(currentIndex == iconIndex) {
        return Colors.white;
      } else {
        return textDisabledColor;
      }
    }
    
    Future<void> _onItemTapped(BuildContext context, int newIndex) async {
      String? view = _getViewFromMenu(newIndex);
      await Navigator.of(context).pushNamed(view);
    }
    
    String? _getViewFromMenu(int newIndex) {
      String? view;
      switch(newIndex) {
        case 0: view = Tab1View.routeName; break;
        case 1: view = Tab2View.routeName; break;
        case 2: view = Tab3View.routeName; break;
        case 3: view = Tab4View.routeName; break;
        default: view = null;
      }
      return view;
    }
    

    And this is how I build the PlatformNavBar object inside a StatefulWidget:

    @override
      Widget build(BuildContext context) {
    
        assignIndex(context);
    
        final platformNavBar = getPlatformNavBar(context, widget._myService.bottomBarSelectedIndex, (index) {
          setState(() {
            assignIndex(context);
          });
        });
    
        return PlatformScaffold(
          bottomNavBar: platformNavBar,
          backgroundColor: Colors.white,
          body: _ScaffoldBody(
              baseScaffoldService: widget._myService,
              childBuilder: widget.childBuilder,
            ),
        );
    
      }
    
      void assignIndex(BuildContext context) {
        final int currentIndex = NavUtils.getCurrentMenuIndex(context); //a method that get the name of the route from ModalRoute and map it to an index
        if(currentIndex > -1) {
          widget._myService.bottomBarSelectedIndex = currentIndex;
        }
      }
    

    Flutterversion:

    Flutter 3.3.6 • channel stable • https://github.com/flutter/flutter.git
    Framework • revision 6928314d50 (4 days ago) • 2022-10-25 16:34:41 -0400
    Engine • revision 3ad69d7be3
    Tools • Dart 2.18.2 • DevTools 2.15.0
    

    Flutter Platform Widget version: ^2.0.0

    Do you have any clue about this? Am I doing something wrong or is it a bug?

    opened by Automatik 0
  • How to Interchange PlatformTabScaffold with PlatformScaffold

    How to Interchange PlatformTabScaffold with PlatformScaffold

    I am building an app with PlatformTabScaffold, with a BottomNavigationBar.

    However, I need login and logout pages without any Tabs and implement those pages using PlatformScaffold.

    During startup, I go to the login page and then use pushAndRemoveUntil to go to the page with the tabs, and the code works.

    However, I have a logout button that logs the user out and then goes to the Login page to allow the use to login again.

    The problem is that when the login page pushes again, to the Tabbed pages, I end up with with 2 sets of tabs along the bottom!

    This only happens on IOS, not on Android.

    Is there a way to reset the environment to use either one or the other Scaffold, interchangeably?

    I can provide source, but I'll have to strip my app down. Let me know if needed.

    Thanks, Rudy

    opened by rlfolden 0
  • SnackBars not showing on iOS when PlatformNavBar and PlatformScaffold are used together

    SnackBars not showing on iOS when PlatformNavBar and PlatformScaffold are used together

    The issue #252 is closed saying it's not an issue of the package, but it indeed is. Normally snack bars show totally fine on iOS, but not when PlatformNavBar and PlatformScaffold are used together. (When there is no PlatformNavBar, snack bars show without any problem)

    opened by ercantomac 0
Owner
null
Purpose of this project is to create extendable architecture of making platform aware Widgets which automatically select platform specific implementation

Old good factory Main obstacle in creating native experience on Flutter is the fact that you are asked to rebuild two layouts using platform specific

Swav Kulinski (Robotoaster) 101 Oct 14, 2022
This project provides an amazing widget for using the specific inputfield for the specific platform

This project provides an amazing widget for using the specific inputfield for the specific platform

Kovács Levente 0 Apr 12, 2022
Cupertino app codelab - Building a Cupertino App with Flutter

Building a Cupertino App with Flutter Flutter allows us creating Cupertino (iOS-

Abdulaziz Malikov 5 Nov 30, 2022
Cupertino back gesture - Flutter package to set custom width of iOS back swipe gesture area

cupertino_back_gesture A Flutter package to set custom width of iOS back swipe gesture area. Usage To use this package, add cupertino_back_gesture as

null 28 Dec 7, 2022
ESP-Touch Dart API for Flutter. Platform-specific implementation for Android (Java) and iOS (Objective-C).

esptouch_flutter Flutter plugin for ESP-Touch to configure network for ESP-8266 and ESP-32 devices. Runs on iOS and Android. esptouch_flutter is Flutt

SMAHO Engineering OSS 86 Dec 10, 2022
A flutter application that allows users to test their knowledge through quizzes made for specific topics.

Quiz_App A flutter application that allows users to test their knowledge through quizzes made for specific topics. Setup The application consists of a

null 0 Dec 29, 2021
Cupertino version of the Material Stepper in Flutter

Cupertino Stepper for Flutter Cupertino version of the stock Material Stepper in Flutter. NOTE: This is not the same as the UIStepper control on iOS.

J-P Nurmi 18 Oct 13, 2022
Material & Cupertino SpinBox for Flutter

SpinBox for Flutter SpinBox for Flutter is a numeric input widget with an input field for entering a specific value, and spin buttons for quick, conve

J-P Nurmi 26 Nov 30, 2022
The Material Design Icons Icon pack available as set of Flutter Icons.

material_design_icons_flutter The Material Design Icons Icon pack available as set of Flutter Icons. Based on Material Design Icons 6.5.95. See a web

ziofat 147 Oct 26, 2022
Mask Aware Face Attendance App built using Flutter

Face Attendance An App Made with Face SDK record.mp4 Before we get started ?? For now, Our app does support only Android platform (arm64). ?? You will

FaceOnLive 113 Dec 30, 2022
Memebaaz is a video/images sharing app, Anyone can share short videos and images through app, the media will go through admin's approval.

MemeBaaz - Memes & Short Videos App Memebaaz is a Video/images Sharing App, Anyone can share short videos and images through app, the media will go th

Rakesh K. 18 Nov 14, 2022
📐 It's a set of common utility strategies to work with responsive styles with Flutter and CSS in JS

@displaykit/responsive_styles You don't need to be worried just because you have to support multiple screens ?? ?? ?? ?? . It's a set of common utilit

DisplayKit Tech 42 Dec 16, 2022
Material io ext - A collection of extensions for creating widgets following material.io guidelines

material_io_ext It is a collection of extensions for creating widgets following

BetterX.io 3 Jan 28, 2022
A flutter widget that animates scrolling through a set of fixed size containers.

Spinner This flutter package implements a simple Spinner animation that cycles through any number of fixed size child widgets. Useful for selecting a

Mark Schmidt 6 Aug 3, 2021
A Very Flexible Widget that can Implement Material Sheets on all Directions, both modal and persistent, and consequently a Material Navigation Drawer

Flutter_MaterialSheetAndNavigationDrawer If this project helped you reduce developement time or you just want to help me continue making useful tools

Bryan Cancel 30 Dec 4, 2021
A Flutter widget to set time with spinner instead of material time picker

flutter_time_picker_spinner Time Picker widget with spinner instead of a material time picker. 12H format 24H format 24H format with second Custom sty

Bobby Stenly Irawan 34 Aug 8, 2022
A flutter app to practice some common and important widgets

Flutter Beginner 2 A flutter app to practice some common and important widgets Developer Alexander Sosa (https://www.linkedin.com/in/alexander-sosa-as

Alexander Sosa 0 Jan 3, 2022
The domain specific language in dart for flutter widgets.

Rettulf !esrever ni stegdiw etirW Getting started import 'package:rettulf/rettulf.dart'; void main() => const MyApp().runAsApp(); class MyApp extend

Li plum 4 Dec 21, 2022
Weibo@Flow - A third party Weibo client for Android with Material You theming (iOS version later). 💪 Powered by Flutter 💪

Weibo@Flow - A third party Weibo client for Android with Material You theming (iOS version later). ?? Powered by Flutter ??

妇校长 6 Sep 19, 2022