flutter_platform_widgets

repository·master·Indexed 23 days ago

https://github.com/stryder-dev/flutter_platform_widgets

A wrapper library for Flutter that simplifies targeting Material and Cupertino design languages using a single widget API. It provides platform-aware widgets, such as PlatformAppBar and PlatformCheckbox, that automatically render the correct underlying widget based on the target platform (Android, iOS, Web, macOS, Windows, Linux). Note: This package is discontinued and no longer supported due to Flutter splitting Material and Cupertino widgets into separate packages.

Tokens
14.3K
Snippets
20
Records
48
Agent score
82%

What's inside flutter_platform_widgets

  1. What is flutter_platform_widgets?

    master

    The flutter_platform_widgets package provides a set of platform-aware widgets that automatically switch between Material (Android) and Cupertino (iOS/macOS) implementations based on the current target platform. This eliminates the need for manual conditional logic (e.g., if (platform == TargetPlatform.iOS) ...) throughout your codebase.

    Instead of writing separate branches for different platforms, you use Platform prefixed widgets like PlatformElevatedButton.

    Widget build(BuildContext context) {
      return PlatformElevatedButton(
          onPressed: () => onAction(),
          child: PlatformText('Action'),
        );
    }
  2. How platform widgets handle platform-specific differences

    master

    Platform widgets in this package act as wrappers around Material and Cupertino widgets. They attempt to map common properties to the primary constructor arguments to provide a unified API.

    When properties diverge between platforms, you can provide platform-specific configuration using the material and cupertino 'enhancing' properties. This allows you to customize the underlying widget without losing the platform-switching abstraction.

    Note: Most widgets directly map properties to their underlying platform widgets to avoid imposing an opinionated structure, with the exception of PlatformScaffold and PlatformTabScaffold.

  3. How platform widgets work

    master

    Instead of writing manual conditional logic using Platform.isAndroid or Platform.isIOS to switch between Material and Cupertino widgets, you can use a single platform widget. These widgets automatically render the correct underlying widget based on the ThemeData.platform property.

    Supported design languages/platforms include:

    • Android
    • iOS
    • Web
    • Macos
    • Windows
    • Linux
    // Instead of manual platform checks:
    if (Platform.isAndroid) {
      return ElevatedButton(onPressed: onPressed, child: child);
    } else if (Platform.isIOS) {
      return CupertinoButton.filled(onPressed: onPressed, child: child);
    }
    
    // Use a single platform widget:
    return PlatformElevatedButton(onPressed: onPressed, child: child);
  4. Sync Material and Cupertino themes using MaterialBasedCupertinoThemeData

    master

    To ensure your Cupertino widgets share the same visual configuration as your Material app, use MaterialBasedCupertinoThemeData.

    This requires three steps:

    1. Create a ThemeData instance for Material.
    2. Wrap your app in a Theme widget using that ThemeData (required for widgets using Theme.of(context)).
    3. Pass the materialTheme to MaterialAppData and wrap it in MaterialBasedCupertinoThemeData for the CupertinoAppData.
    final materialTheme = ThemeData(
      primarySwatch: Colors.green,
    );
    
    return Theme(
      data: materialTheme,
      child: PlatformProvider(
        builder: (context) => PlatformApp(
          localizationsDelegates: ..., 
          title: ..., 
          home: ..., 
          material: (_, __) => MaterialAppData(
            theme: materialTheme,
          ),
          cupertino: (_, __) => CupertinoAppData(
            theme: MaterialBasedCupertinoThemeData(materialTheme: materialTheme),
          ),
        ),
      ),
    );
  5. Configure Light and Dark themes for Cupertino using CupertinoDynamicColor

    master

    Unlike Material, CupertinoThemeData handles brightness changes using CupertinoDynamicColor. Instead of providing two different theme objects, you set individual properties to a CupertinoDynamicColor instance, which defines both a color (for light mode) and a darkColor (for dark mode).

    final cupertinoTheme = CupertinoThemeData(
      primaryColor: CupertinoDynamicColor.withBrightness(
        color: Colors.red,
        darkColor: Colors.blue,
      ),
    );
  6. Define a custom CupertinoTheme directly

    master

    If you want your Cupertino UI to look distinct from your Material UI, you can provide a standalone CupertinoThemeData instead of deriving it from Material. Pass this instance directly to the theme property of CupertinoAppData.

    final materialTheme = ThemeData(
      primarySwatch: Colors.green,
    );
    final cupertinoTheme = CupertinoThemeData(
      primaryColor: Colors.red,
    );
    
    return Theme(
      data: materialTheme,
      child: PlatformProvider(
        builder: (context) => PlatformApp(
          localizationsDelegates: ..., 
          title: ..., 
          home: ..., 
          material: (_, __) => MaterialAppData(
            theme: materialTheme,
          ),
          cupertino: (_, __) => CupertinoAppData(
            theme: cupertinoTheme,
          ),
        ),
      ),
    );
  7. Use PlatformApp.router for Navigator 2.0

    master

    If your application uses Navigator 2.0, use the PlatformApp.router constructor within a PlatformProvider to maintain platform-specific styling and behavior.

    PlatformProvider(
      builder: (context) => PlatformApp.router(
        localizationsDelegates: <LocalizationsDelegate<dynamic>>[
          DefaultMaterialLocalizations.delegate,
          DefaultWidgetsLocalizations.delegate,
          DefaultCupertinoLocalizations.delegate,
        ],
        title: 'Flutter Platform Widgets',
        routeInformationParser: ...,
        routerDelegate: ...
      ),
    )
  8. Use Material widgets within a Cupertino app

    master

    By default, using Material widgets (like ListTile) inside a Cupertino-styled app will throw an exception because they cannot find a Material widget parent. To allow Material widgets to work within your Cupertino app, configure PlatformProvider with PlatformSettingsData(iosUsesMaterialWidgets: true).

    PlatformProvider(
      settings: PlatformSettingsData(iosUsesMaterialWidgets: true),
      builder: ...
    )
  9. Configure PlatformApp for iOS-like behavior

    master

    While flutter_platform_widgets works with a standard MaterialApp, using PlatformApp provides styling and behavior closer to the actual iOS (Cupertino) platform. When using PlatformApp, you should include localizationsDelegates to ensure Cupertino widgets function correctly, as many expect localization to be configured.

    For standard navigation, use PlatformApp. For Navigator 2.0, use PlatformApp.router.

    PlatformProvider(
      builder: (context) => PlatformApp(
        localizationsDelegates: <LocalizationsDelegate<dynamic>>[
          DefaultMaterialLocalizations.delegate,
          DefaultWidgetsLocalizations.delegate,
          DefaultCupertinoLocalizations.delegate,
        ],
        title: 'Flutter Platform Widgets',
        home: MyHomePage(),
      ),
    )
  10. Customize iOS launch screen assets

    master

    To customize the iOS launch screen, you can replace the image files located in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.

    Alternatively, you can manage these assets through Xcode:

    1. Open the iOS workspace using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, select Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  11. Configure Light and Dark themes for Material

    master

    To support light and dark modes in Material, create two separate ThemeData instances with different brightness properties. Provide them to MaterialAppData using the theme (for light) and darkTheme (for dark) parameters.

    final materialLightTheme = ThemeData(
      brightness: Brightness.light,
      primarySwatch: Colors.green,
    );
    final materialDarkTheme = ThemeData(
      brightness: Brightness.dark,
      primarySwatch: Colors.cyan,
    );
    
    return Theme(
      data: materialTheme,
      child: PlatformProvider(
        builder: (context) => PlatformApp(
          localizationsDelegates: ..., 
          title: ..., 
          home: ..., 
          material: (_, __) => MaterialAppData(
            theme: materialLightTheme,
            darkTheme: materialDarkTheme,
          ),
          cupertino: ..., 
        ),
      ),
    );