{"id":24714446,"url":"https://github.com/ml-opensource/platty","last_synced_at":"2026-01-11T04:46:50.815Z","repository":{"id":56837027,"uuid":"158414251","full_name":"ml-opensource/platty","owner":"ml-opensource","description":"Platform-adapting flutter widgets.","archived":false,"fork":false,"pushed_at":"2021-04-28T15:20:11.000Z","size":1182,"stargazers_count":64,"open_issues_count":1,"forks_count":1,"subscribers_count":21,"default_branch":"master","last_synced_at":"2025-04-03T01:41:31.608Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ml-opensource.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-20T15:49:57.000Z","updated_at":"2025-04-01T07:51:13.000Z","dependencies_parsed_at":"2022-09-09T19:10:14.580Z","dependency_job_id":null,"html_url":"https://github.com/ml-opensource/platty","commit_stats":null,"previous_names":["ml-opensource/platty","fuzz-productions/platty"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ml-opensource/platty","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-opensource%2Fplatty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-opensource%2Fplatty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-opensource%2Fplatty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-opensource%2Fplatty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ml-opensource","download_url":"https://codeload.github.com/ml-opensource/platty/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ml-opensource%2Fplatty/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001443,"owners_count":26083078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-27T08:16:37.673Z","updated_at":"2025-10-09T12:31:36.544Z","avatar_url":"https://github.com/ml-opensource.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# platty\n\nPlatform Conforming Widgets for Flutter!\n\nFlutter makes no attempt to provide familiar widgets for a specific platform (unlike React Native, ionic, and other cross platform tooling). \nThis has enormous benefits to unified rendering on all platforms, maximum flexibility, and eliminating a whole class of bugs and testing done for \neach platform. While this is great, many scenarios we want our apps to look and feel like an Android or iOS app. \nPlatty allows you to render iOS (Cupertino) and Android (Material) like widgets with minimal effort and maximum control in a unified \nAPI. \n\nNo more checking for platform inside render blocks to render a `CupertinoButton` or `FlatButton`, let `platty` do the logic for you! \nWant to use bottom tabs in your app that resolve to platform specific UI? No problem! \n\n## Widgets\n\nList of Widget Files:\n\n[PAlertDialog](/lib/src/widgets/alert.dart)\n\n[PBackButton](/lib/src/widgets/back_button.dart)\n\n[PButton/PFlatButton](/lib/src/widgets/button.dart)\n\n[PNavigationBar/PSliverNavigationBar](/lib/src/widgets/navigation_bar.dart)\n\n[PActivityIndicator](/lib/src/widgets/progress.dart)\n\n[PRoute](/lib/src/widgets/routing.dart)\n\n[PScaffold](/lib/src/widgets/scaffold.dart)\n\n[PSlider](/lib/src/widgets/slider.dart)\n\n[PSwitch](/lib/src/widgets/switches.dart)\n\n[PTabBar](/lib/src/widgets/tabs.dart)\n\n[PTextField](/lib/src/widgets/text_field.dart)\n\n\n## Getting Started\n\nUse platty to unify render-specific APIs for you. The library utilizes the `BuildContext` theming APIs to propagate platform \ninformation into the Widgets.\n\nBy default, all widgets conform to the   default `TargetPlatform`. It looks up the `Theme.of(context).platform` for its default.\nAlso, all widgets provide a `renderPlatform` prop that allows you to choose which one to render (if you wish).\n\nReplace `MaterialApp` and `CupertinoApp` with `PlatformApp`:\n\n```dart\n\nclass MyApp extends StatelessWidget {\n  // This widget is the root of your application.\n  @override\n  Widget build(BuildContext context) {\n    return PlatformApp(\n      title: 'Flutter Demo',\n      // specify our app theme here. We do the leg work of bridging it to Cupertino.\n      unifiedTheme: ThemeData(\n            colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.red),\n            bottomAppBarColor: Colors.red,\n          ),\n      home: ExamplePage(),\n    );\n  }\n}\n\n```\n\n`PlatformApp` unifies all of the same properties between `MaterialApp` and `CupertinoApp` to allow both instances of widgets in the hiearchy and \nswitching styling based on platform.\n\nNow you replace widgets that are included in this library with their \"P\" counterparts:\n\n## Buttons\n\n`Button`/`CupertinoButton` -\u003e `PButton`\n[Source](/example/lib/button_page.dart)\n\n`FlatButton`/`CupertinoButton` -\u003e `PFlatButton`\n[Source](/example/lib/button_page.dart)\n\nBelow is a side-by-side comparison of the different button states. Note \nhow iOS and Android have similar theming. \n\n![Button Example](/screenshots/buttons.png)\n\n## Navigation Bars\n\n`AppBar`/`CupertinoNavigationBar` -\u003e `PNavigationBar`\n\n![Android Nav](/screenshots/androidnav.png)\n![iOS Nav](/screenshots/iosnav.png)\n\nBy default, the `PNavigationBar` on iOS will mirror Material Android theming. This \nmeans button tint and text style of the title will match. \nIf you wish to change that, set  `iosMirrorAndroid: false`. Otherwise \nit will default to cupertino theming:\n\n![Plain iOS Nav](/screenshots/plain_ios_nav.png)\n\n[Source](/example/lib/navigation_bar_page.dart)\n\n`SliverAppBar`/`CupertinoSliverNavigationBar` -\u003e `PSliverNavigationBar`\n\n## Sliders\n\n`Slider`/`CupertinoSlider` -\u003e `PSlider`\n\n![Sliders](/screenshots/sliders.png)\n\n[Source](/example/lib/sliders_page.dart)\n\n## Switches\n\n`Switch`/`CupertinoSwitch` -\u003e `PSwitch`\n\n![Switch](/screenshots/switches.png)\n\n[Source](/example/lib/switches_page.dart)\n\n## Inputs\n\n`TextField/CupertinoTextField` -\u003e `PTextField`\n\n![TextField](/screenshots/inputs.png)\n\nBy default, the `PTextField` on iOS will mirror Android styling and decoration (map `OutlineInputBorder` to a similar outline \nfor iOS). Also `PTextField` on iOS will show `helperText` and `errorText` (even though not native iOS widget).\n## Bottom Navigation\n\n`BottomNavigationBar`/`CupertinoTabBar` -\u003e `PTabBar`\n\n![Bottom Navigation Android](/screenshots/androidtabs.png)\n![Bottom Navigation iOS](/screenshots/iostabs.png)\n\n[Source](/example/lib/tabs_page.dart)\n\n## Scaffold\n\n`Scaffold`/`CupertinoScaffold` -\u003e `PScaffold`\n\n## Progress Indicators\n\n`CircularProgressIndicator`/`CupertinoActivityIndicator` -\u003e `PActivityIndicator`\n\n![Progress](/screenshots/progress.png)\n\n[Source](/example/lib/progress_page.dart)\n\n## Back Button\n\n`BackButton`/`CupertinoNavigationBarBackButton` -\u003e `PBackButton`\n\n## Alerts\n\n`AlertDialog`/`CupertinoAlertDialog` -\u003e `PAlertDialog`\n\n![Android Alert](/screenshots/androidalert.png)\n![Ios Alert](/screenshots/iosalert.png)\n\n[Source](/example/lib/alert_page.dart)\n\nThe `Alert` expect a `List\u003cWidget\u003e`. When feeding `PFlatButton`, utilize \nthe helper methods to theme the buttons properly for iOS:\n\n```dart\nPAlertDialog(\n  title: Text(\"Sample Alert\"),\n  content:\n      Text(\"I can adapt based on target platform defaults, PTheme wrapper, \"\n          \"or individual render platform overrides.\"),\n  actions: \u003cWidget\u003e[\n    PFlatButton.alertPrimary(\n      text: \"Ok\",\n      onPressed: () {\n        Navigator.of(context).pop();\n      },\n    ),\n    PFlatButton.alertSecondary(\n      text: \"Cancel\",\n      onPressed: () {\n        Navigator.of(context).pop();\n      },\n    )\n  ],\n)\n```\n\n### Properties Specific to a platform have a prefix\nAny widgets that have ios-only or android-only counterparts, they are prefixed to `android`/`ios` accordingly:\n\nFor example `PButton`, `androidShape` applies to `RaisedButton.shape` property. It does not exist on a `CupertinoButton`. \nHowever `CupertinoButton` has a `borderRadius` and `pressedOpacity`. Those two props become `iosBorderRadius` and `iosPressedOpacity`.\n\n## Helpers\n\nThis library bundles a few standard functions to easily return code that is unique for each platform. Instead of checking  \nand switching on the result of `Theme.of(context).targetPlatform`, utilize the following methods:\n\n### Specific Platform Instance\n\nTo have a specific `P`-Widget utilize a specific platform theme only, such as Material or Cupertino, you can wrap\nit in a `PTheme` instance:\n\n```dart\nPTheme(\n  data: PThemeData(\n    platform: TargetPlatform.android,  // or iOS\n    child: child,\n  ),\n);\n```\n\nOr, more simply, utilize helper method:\n```dart\nPTheme.ios(child);\nPTheme.android(child);\n```\n\n\nAlso, all `P`-widgets and methods allow you to override the `PTheme` with a `renderPlatform` parameter in their constructor \nor calling method:\n```dart\nPButton(\"Hello Android\", \n  renderPlatform: TargetPlatform.Android,\n)\n```\nThis will swap the rendering over to `Material` widgets for this specific widget.\n\n__Note__: Wrapping a widget with the `PTheme` will propagate that instance down the widget hierarchy and is thus preferred than \nmanually specifying the `renderPlatform` for each individual widget. \n\n### Creating Your Own Platform-Adapting Widgets\n\nWe can extend upon the logic included in this library to build our own, powerful platform-adapting widgets.\nIncluded in the library is the `PlatformAdaptingWidget` base class, which inherits from `StatelessWidget`.\n\n\n```dart\nclass SamplePlatformWidget extends PlatformAdaptingWidget {\n  final Color color;\n\n  SamplePlatformWidget({Key key, @required this.color, TargetPlatform renderPlatform}) // should allow consumers to choose TargetPlatform\n      : super(key: key, renderPlatform: renderPlatform);\n\n  /// Render a material widget here. Most Material widgets require a Material Theme instance above it.\n  @override\n  get renderMaterial =\u003e (BuildContext context) {\n        return BackButton(\n          color: color,\n        );\n      };\n\n  /// Render a cupertino widget here.\n  @override\n  get renderCupertino =\u003e (BuildContext context) {\n        return CupertinoNavigationBarBackButton(\n          color: color,\n        );\n      };\n  \n  /// Render a fuchsia widget here. (defaults to material)\n    @override\n    get renderFuchsia =\u003e (BuildContext context) {\n          return BackButton(\n            color: color,\n          );\n        };\n}\n```\n\n### Platform-specific logic\n\nThis library comes with a few standard ways to implement behavior based on platform.\nYou can utilize `platformWrap`, which allows you to specify a `child`, and on 1 or all platforms, wrap it \nwith another widget:\n\n```dart\nplatformWrap(\n      context,\n      child: PButton(\n        padding: EdgeInsets.all(0.0),\n        child: Text(title),\n        color: Colors.red,\n        onPressed: () {\n          Navigator.push(context, PRoute.of(context, builder: page));\n        },\n      ),\n      renderCupertino: (context, child) =\u003e Padding(\n            padding: EdgeInsets.only(bottom: 8.0),\n            child: child,\n          ),\n    );\n```\nYou can specify any of `renderCupertino`, `renderMaterial`, or `renderFuschia` (or none). \nAny render methods not specified default to the `child`.\n\nAlso, `platformSelect` is a helper that enables returning different objects based on platform in a unified way.\nIn our `PlatformAdaptingWidget`, we utilize it to return a different widget based on platform. You can use it to return any \nreturn type based on platform:\n```dart\n\nColumn(\n  children: [\n    platformSelect(context, \n      renderMaterial: (context) =\u003e Text(\"I am android\"),\n      renderCupertino: (context) =\u003e Text(\"I am iOS\"),\n      renderFuchsia: (context) =\u003e Text(\"I am FUCHSIA\")) \n  ],\n),\n\n```\n\n`renderMaterial` and `renderCupertino` are required. `renderFuchsia` defaults to material.\n\nor you can return a non-widget too:\n```dart\nColumn(\n  children: [\n    Text(platformSelect(context, \n      renderMaterial: (context) =\u003e \"I am android\"),\n      renderCupertino: (context) =\u003e \"I am iOS\",\n      renderFuchsia: (context) =\u003e \"I am FUCHSIA\")) \n  ],\n),\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fml-opensource%2Fplatty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fml-opensource%2Fplatty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fml-opensource%2Fplatty/lists"}