├── .gitattributes ├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── libraries │ ├── Dart_Packages.xml │ ├── Dart_SDK.xml │ └── Flutter_Plugins.xml ├── misc.xml ├── modules.xml ├── vcs.xml └── workspace.xml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── assets │ ├── AssetManifest.json │ ├── FontManifest.json │ ├── LICENSE │ ├── fonts │ │ └── MaterialIcons-Regular.ttf │ └── packages │ │ └── cupertino_icons │ │ └── assets │ │ └── CupertinoIcons.ttf ├── favicon.png ├── flutter_service_worker.js ├── icons │ ├── Icon-192.png │ └── Icon-512.png ├── index.html ├── main.dart.js ├── main.dart.js.map └── manifest.json ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ └── src │ │ │ ├── debug │ │ │ └── AndroidManifest.xml │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── kotlin │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ └── example │ │ │ │ │ └── MainActivity.kt │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── values │ │ │ │ └── styles.xml │ │ │ └── profile │ │ │ └── AndroidManifest.xml │ ├── build.gradle │ ├── example_android.iml │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── example.iml ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── flutter_export_environment.sh │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ │ └── WorkspaceSettings.xcsettings │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ └── LaunchImage.imageset │ │ │ ├── Contents.json │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ └── README.md │ │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── Runner-Bridging-Header.h ├── lib │ ├── main.dart │ ├── screens │ │ ├── details │ │ │ └── details_1.dart │ │ ├── page_1.dart │ │ ├── page_2.dart │ │ ├── page_3.dart │ │ └── page_4.dart │ └── utils │ │ ├── cupertino_navigation_demo.dart │ │ └── pop_up.dart ├── macos │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ ├── GeneratedPluginRegistrant.swift │ │ └── ephemeral │ │ │ └── Flutter-Generated.xcconfig │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── Runner │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── app_icon_1024.png │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ └── app_icon_64.png │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Configs │ │ ├── AppInfo.xcconfig │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── Warnings.xcconfig │ │ ├── DebugProfile.entitlements │ │ ├── Info.plist │ │ ├── MainFlutterWindow.swift │ │ └── Release.entitlements ├── pubspec.lock ├── pubspec.yaml └── web │ ├── favicon.png │ ├── icons │ ├── Icon-192.png │ └── Icon-512.png │ ├── index.html │ └── manifest.json ├── lib ├── app │ └── main_app.dart ├── app_bar │ ├── app_bar.dart │ ├── cupertino │ │ └── search.dart │ └── search_bar.dart ├── button │ ├── icon_button.dart │ ├── raised_button.dart │ └── text_button.dart ├── common │ ├── common_tiles │ │ ├── avatar_title.dart │ │ ├── base_tile.dart │ │ ├── basic_tile.dart │ │ └── phone_tile.dart │ ├── list_tile.dart │ ├── routing.dart │ ├── search │ │ ├── cupertino_search_bar.dart │ │ ├── material_search_bar.dart │ │ └── native_search.dart │ ├── text.dart │ └── widget.dart ├── dialog │ └── alert_dialog.dart ├── icon │ └── icon.dart ├── input │ ├── date_picker.dart │ ├── group_select.dart │ └── text_field.dart ├── layout │ └── device_class.dart ├── native_widgets.dart ├── picker │ ├── picker.dart │ └── selection.dart ├── scaffold │ ├── ios_controllers │ │ ├── master_detail_controller │ │ │ └── controller.dart │ │ ├── navigation_controller.dart │ │ └── table_view_controller │ │ │ ├── cell.dart │ │ │ └── controller.dart │ ├── list_view_scaffold.dart │ ├── master_detail_scaffold.dart │ ├── scaffold.dart │ ├── search_scaffold.dart │ └── tab_scaffold.dart ├── status │ └── circle_indicator.dart ├── switch │ └── switch.dart ├── tabs │ ├── bottom_navigation.dart │ └── top_navigation.dart ├── toolbar │ └── bottom_toolbar.dart └── utils │ ├── data_table.dart │ ├── ios_search_bar.dart │ └── platform_switch.dart ├── native_widgets.iml ├── pubspec.lock ├── pubspec.yaml └── test └── native_widgets_test.dart /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | ios/.generated/ 9 | ios/Flutter/Generated.xcconfig 10 | ios/Runner/GeneratedPluginRegistrant.* 11 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 1.3.7 4 | 5 | * intl: ">=0.15.0 <1.0.0" 6 | 7 | ## 1.3.6 8 | 9 | * Fixing type 10 | * Bumping version 11 | 12 | ## 1.3.5 13 | 14 | * Bump Version 15 | 16 | ## 1.3.3 17 | 18 | * Fix for Sticky Header 19 | 20 | ## 1.3.2 - 05.0629.2019 21 | 22 | * Upgrading Packages 23 | * Working with Flutter dev channel 24 | 25 | ## 1.2.1 - 05.06.2019 26 | 27 | * Upgrading Packages 28 | 29 | ## 1.3.0 - 05.03.2019 30 | 31 | * Adding Support for Desktop 32 | * Updating Example 33 | * Adding Desktop Targets to Example 34 | 35 | ## 1.2.0 - 04.06.2019 36 | 37 | * Making Example Desktop Aware 38 | 39 | ## [1.0.1] 40 | 41 | * Added current index to NativeScaffold's PlatformNavBar. 42 | * Added automaticallyImplyLeading to allow hidden leading element in AppBar. 43 | * Thank you to @amadejkastelic for the PR 44 | 45 | ## [1.0.0] - Major Update 46 | 47 | * Refactored Library to use Platfrom Widgets plugin in the backend 48 | * Added Layout (Mobile, Tablet, Desktop) 49 | * Added Detailed Example 50 | * Added Folder Structure to Library for Easy Documentaion 51 | * Added Cupertino TableViewController, Cell and Search Bar 52 | * Updated Picker 53 | * Added Toolbar 54 | * Added App Bar 55 | * Added Scaffold 56 | * Added Text Button 57 | * Added Icon Button 58 | * Added Routing 59 | * Added Segmented Select 60 | * Updated Bottom Tabs 61 | * Added Top Navigation 62 | * Added Main App 63 | * Added Text Label 64 | * Added Search Widget 65 | * Updated Switch 66 | * Added Confirmation Dialog 67 | * Updated iOS Dialog with Actions 68 | 69 | ## [0.1.2] - Updated Example 70 | 71 | * Updated Example and New Dart Support 72 | 73 | ## [0.1.1] - Bug Fixes and Breaking Changes 74 | 75 | * Native button will now default to 16.0 padding internal 76 | 77 | ## [0.1.0] - Bug Fixes and Breaking Changes 78 | 79 | * Native button will now use Material Button on Android instead of raised button 80 | * You can specify android specific options and cupertino ios options 81 | * There is now internal and external paddign for buttons 82 | 83 | ## [0.0.4] - Bug Fixes 84 | 85 | * Bug Fix for Center Loading Indicator 86 | 87 | ## [0.0.3] - Adding Components 88 | 89 | * Bug Fix for App Bar 90 | 91 | ## [0.0.2] - Adding Components 92 | 93 | * Added App Bar and optional text for Loading Indicator 94 | 95 | ## [0.0.1] - Adding Components 96 | 97 | * Added Button, Switch, Dialog, Loading Indicator, and Tab Bar 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rhodes Davis Jr. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Flutter Community: native_widgets](https://fluttercommunity.dev/_github/header/native_widgets)](https://github.com/fluttercommunity/community) 2 | 3 | [![Buy Me A Coffee](https://img.shields.io/badge/Donate-Buy%20Me%20A%20Coffee-yellow.svg)](https://www.buymeacoffee.com/rodydavis) 4 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WSH3GVC49GNNJ) 5 | ![github pages](https://github.com/fluttercommunity/native_widgets/workflows/github%20pages/badge.svg) 6 | 7 | # Native Widgets 8 | 9 | [![pub package](https://img.shields.io/pub/v/native_widgets.svg)](https://pub.dartlang.org/packages/native_widgets) 10 | 11 | A Flutter plugin to show the correct widgets for iOS and Android. 12 | 13 | Avoid duplicating code and just write once for supported widgets. 14 | 15 | Android will use Material Design and iOS will use Cupertino style widgets. 16 | 17 | Online Demo: https://fluttercommunity.github.io/native_widgets/ 18 | 19 | ## Usage 20 | 21 | To use this plugin, add `native_widgets` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). 22 | 23 | Look at the example for various ways to use this plugin! 24 | -------------------------------------------------------------------------------- /docs/assets/AssetManifest.json: -------------------------------------------------------------------------------- 1 | {"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]} -------------------------------------------------------------------------------- /docs/assets/FontManifest.json: -------------------------------------------------------------------------------- 1 | [{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.ttf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]},{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.ttf"}]}] -------------------------------------------------------------------------------- /docs/assets/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/docs/assets/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /docs/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/docs/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf -------------------------------------------------------------------------------- /docs/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/docs/favicon.png -------------------------------------------------------------------------------- /docs/flutter_service_worker.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const CACHE_NAME = 'flutter-app-cache'; 3 | const RESOURCES = { 4 | "/index.html": "e36211d86e9c70409c58295974f749a1", 5 | "/main.dart.js": "fb604667472ef3b7cc78860425fef951", 6 | "/favicon.png": "5dcef449791fa27946b3d35ad8803796", 7 | "/icons/Icon-192.png": "ac9a721a12bbc803b44f645561ecb1e1", 8 | "/icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1", 9 | "/manifest.json": "00e0b69b49487ce4f9ff0c5fac8fda49", 10 | "/assets/LICENSE": "1502721d45cdb6c295a383cdd15fb963", 11 | "/assets/AssetManifest.json": "2efbb41d7877d10aac9d091f58ccd7b9", 12 | "/assets/FontManifest.json": "f7161631e25fbd47f3180eae84053a51", 13 | "/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "9a62a954b81a1ad45a58b9bcea89b50b", 14 | "/assets/fonts/MaterialIcons-Regular.ttf": "56d3ffdef7a25659eab6a68a3fbfaf16" 15 | }; 16 | 17 | self.addEventListener('activate', function (event) { 18 | event.waitUntil( 19 | caches.keys().then(function (cacheName) { 20 | return caches.delete(cacheName); 21 | }).then(function (_) { 22 | return caches.open(CACHE_NAME); 23 | }).then(function (cache) { 24 | return cache.addAll(Object.keys(RESOURCES)); 25 | }) 26 | ); 27 | }); 28 | 29 | self.addEventListener('fetch', function (event) { 30 | event.respondWith( 31 | caches.match(event.request) 32 | .then(function (response) { 33 | if (response) { 34 | return response; 35 | } 36 | return fetch(event.request, { 37 | credentials: 'include' 38 | }); 39 | }) 40 | ); 41 | }); 42 | -------------------------------------------------------------------------------- /docs/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/docs/icons/Icon-192.png -------------------------------------------------------------------------------- /docs/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/docs/icons/Icon-512.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .atom/ 3 | .dart_tool/ 4 | .idea 5 | .vscode/ 6 | .packages 7 | .pub/ 8 | build/ 9 | ios/.generated/ 10 | packages 11 | .flutter-plugins 12 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 92f7e16312d9c7c396c0100dcb699458c3f10172 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # native_widgets 2 | 3 | ``` dart 4 | import 'package:flutter/material.dart'; 5 | import 'package:native_widgets/native_widgets.dart'; 6 | 7 | import '../utils/pop_up.dart'; 8 | 9 | class Page1 extends StatefulWidget { 10 | @override 11 | _Page1State createState() => _Page1State(); 12 | } 13 | 14 | class _Page1State extends State { 15 | bool _active = false; 16 | int _selected = 0; 17 | String _value = "Apple"; 18 | bool _switch = true; 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return Scaffold( 23 | appBar: NativeAppBar( 24 | leading: Container( 25 | padding: EdgeInsets.only(top: 10.0), 26 | child: NativeTextButton( 27 | label: "Cancel", 28 | onPressed: () { 29 | FocusScope.of(context).requestFocus(new FocusNode()); 30 | }, 31 | ), 32 | ), 33 | title: const Text("Input Form"), 34 | actions: [ 35 | Container( 36 | padding: EdgeInsets.only(top: 10.0), 37 | child: NativeTextButton( 38 | label: "Save", 39 | style: TextStyle(fontWeight: FontWeight.bold), 40 | onPressed: () { 41 | FocusScope.of(context).requestFocus(new FocusNode()); 42 | }, 43 | ), 44 | ), 45 | ], 46 | ), 47 | body: SingleChildScrollView( 48 | child: ListBody( 49 | children: [ 50 | ListTile( 51 | title: const Text("Loading Indicator..."), 52 | trailing: NativeLoadingIndicator(), 53 | ), 54 | ListTile( 55 | title: const Text("Switch"), 56 | trailing: NativeSwitch( 57 | value: _active, 58 | onChanged: (bool value) => setState(() => _active = value), 59 | ), 60 | ), 61 | Container(height: 20.0), 62 | NativeGroupSelect( 63 | groupValue: _selected, 64 | children: { 65 | 0: Text('Midnight'), 66 | 1: Text('Viridian'), 67 | 2: Text('Cerulean'), 68 | }, 69 | onValueChanged: (int value) { 70 | setState(() { 71 | _selected = value; 72 | }); 73 | }, 74 | ), 75 | NativeSelection( 76 | value: _value, 77 | items: [ 78 | "Apple", 79 | "Orange", 80 | "Pineapple", 81 | "Cherry", 82 | ], 83 | onChanged: (String value) { 84 | setState(() { 85 | _value = value; 86 | }); 87 | }, 88 | ), 89 | NativeListTile( 90 | title: const Text("Power Saver"), 91 | // subtitle: Text("Puts Device into Low Power Mode"), 92 | // hideLeadingIcon: true, 93 | ios: CupertinoListTileData( 94 | style: CupertinoCellStyle.basic, 95 | ), 96 | trailing: [ 97 | NativeSwitch( 98 | value: _switch, 99 | onChanged: (bool value) { 100 | setState(() { 101 | _switch = value; 102 | }); 103 | }), 104 | ], 105 | ), 106 | Container( 107 | padding: const EdgeInsets.all(20.0), 108 | child: NativeButton( 109 | child: const Text("Submit"), 110 | // padding: const EdgeInsets.all(20.0), 111 | color: Colors.blue, 112 | onPressed: () => showAlertPopup(context, 113 | title: "Native Dialog", detail: "Button Submitted!"), 114 | ), 115 | ), 116 | ], 117 | ), 118 | ), 119 | ); 120 | } 121 | } 122 | 123 | ``` -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 28 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.example" 42 | minSdkVersion 16 43 | targetSdkVersion 28 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.debug 54 | } 55 | } 56 | } 57 | 58 | flutter { 59 | source '../..' 60 | } 61 | 62 | dependencies { 63 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 64 | testImplementation 'junit:junit:4.12' 65 | androidTestImplementation 'androidx.test:runner:1.1.1' 66 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 67 | } 68 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 19 | 23 | 27 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import androidx.annotation.NonNull; 4 | import io.flutter.embedding.android.FlutterActivity 5 | import io.flutter.embedding.engine.FlutterEngine 6 | import io.flutter.plugins.GeneratedPluginRegistrant 7 | 8 | class MainActivity: FlutterActivity() { 9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { 10 | GeneratedPluginRegistrant.registerWith(flutterEngine); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /example/android/example_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip 7 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /example/example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=/usr/local/Caskroom/flutter/1.2.1/flutter" 4 | export "FLUTTER_APPLICATION_PATH=/Users/rodydavis/Developer/GitHub/plugins/packages/native_widgets/example" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_TARGET=lib/main.dart" 7 | export "FLUTTER_BUILD_DIR=build" 8 | export "FLUTTER_BUILD_NAME=1.0.0" 9 | export "FLUTTER_BUILD_NUMBER=1" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=false" 12 | export "TREE_SHAKE_ICONS=false" 13 | export "PACKAGE_CONFIG=.packages" 14 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_localizations/flutter_localizations.dart'; 3 | import 'package:native_widgets/native_widgets.dart'; 4 | 5 | import 'screens/page_1.dart'; 6 | import 'screens/page_2.dart'; 7 | import 'screens/page_3.dart'; 8 | import 'screens/page_4.dart'; 9 | import 'dart:io' show Platform; 10 | import 'package:flutter/foundation.dart'; 11 | 12 | // The existing imports 13 | // !! Keep your existing impots here !! 14 | 15 | /// main is entry point of Flutter application 16 | void main() { 17 | // Desktop platforms aren't a valid platform. 18 | if (!kIsWeb) _setTargetPlatformForDesktop(); 19 | return runApp(MyApp()); 20 | } 21 | 22 | /// If the current platform is desktop, override the default platform to 23 | /// a supported platform (iOS for macOS, Android for Linux and Windows). 24 | /// Otherwise, do nothing. 25 | void _setTargetPlatformForDesktop() { 26 | TargetPlatform targetPlatform; 27 | if (Platform.isMacOS) { 28 | targetPlatform = TargetPlatform.iOS; 29 | } else if (Platform.isLinux || Platform.isWindows) { 30 | targetPlatform = TargetPlatform.android; 31 | } 32 | if (targetPlatform != null) { 33 | debugDefaultTargetPlatformOverride = targetPlatform; 34 | } 35 | } 36 | 37 | class MyApp extends StatelessWidget { 38 | @override 39 | Widget build(BuildContext context) { 40 | return new MaterialApp( 41 | localizationsDelegates: >[ 42 | GlobalMaterialLocalizations.delegate, 43 | GlobalWidgetsLocalizations.delegate, 44 | ], 45 | supportedLocales: const [ 46 | Locale('en', 'US'), 47 | Locale('he', 'IL'), 48 | ], 49 | home: NativeAppLook(), 50 | ); 51 | } 52 | } 53 | 54 | class NativeAppLook extends StatelessWidget { 55 | @override 56 | Widget build(BuildContext context) { 57 | return NativeTabScaffold( 58 | tabs: [ 59 | BottomNavigationBarItem( 60 | icon: Icon(Icons.info), 61 | title: Text("Info"), 62 | ), 63 | BottomNavigationBarItem( 64 | icon: Icon(Icons.search), 65 | title: Text("Search"), 66 | ), 67 | BottomNavigationBarItem( 68 | icon: Icon(Icons.list), 69 | title: Text("Table"), 70 | ), 71 | ], 72 | pages: [ 73 | NativeTabView( 74 | title: "Input Form", 75 | child: Page1(), 76 | ), 77 | NativeTabView( 78 | title: "Nav Demo", 79 | child: Page2(), 80 | ), 81 | NativeTabView( 82 | title: "Table View", 83 | child: Page3(), 84 | ), 85 | ], 86 | ); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /example/lib/screens/details/details_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:native_widgets/native_widgets.dart'; 3 | 4 | class DetailsScreen extends StatelessWidget { 5 | @override 6 | Widget build(BuildContext context) { 7 | return Scaffold( 8 | // appBar: NativeAppBar( 9 | // title: Text("Details"), 10 | // ios: CupertinoNavigationBarData( 11 | // heroTag: "Details", 12 | // previousPageTitle: "List View", 13 | // transitionBetweenRoutes: false, 14 | // ), 15 | // ), 16 | // body: Container(), 17 | body: CupertinoPageScaffold( 18 | child: CustomScrollView( 19 | semanticChildCount: 2, 20 | slivers: [ 21 | CupertinoSliverNavigationBar( 22 | // trailing: trailingButtons, 23 | // middle: Text("Presidents"), 24 | largeTitle: Text("Details"), 25 | // previousPageTitle: "", 26 | ), 27 | SliverToBoxAdapter( 28 | child: Container(), 29 | ), 30 | ], 31 | ), 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/lib/screens/page_1.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:native_widgets/native_widgets.dart'; 3 | 4 | import '../utils/pop_up.dart'; 5 | 6 | class Page1 extends StatefulWidget { 7 | @override 8 | _Page1State createState() => _Page1State(); 9 | } 10 | 11 | class _Page1State extends State { 12 | bool _active = false; 13 | int _selected = 0; 14 | String _value = "Apple"; 15 | bool _switch = true; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Scaffold( 20 | appBar: NativeAppBar( 21 | leading: Container( 22 | padding: EdgeInsets.only(top: 10.0), 23 | child: NativeTextButton( 24 | label: "Cancel", 25 | onPressed: () { 26 | FocusScope.of(context).requestFocus(new FocusNode()); 27 | }, 28 | ), 29 | ), 30 | title: const Text("Input Form"), 31 | actions: [ 32 | Container( 33 | padding: EdgeInsets.only(top: 10.0), 34 | child: NativeTextButton( 35 | label: "Save", 36 | style: TextStyle(fontWeight: FontWeight.bold), 37 | onPressed: () { 38 | FocusScope.of(context).requestFocus(new FocusNode()); 39 | }, 40 | ), 41 | ), 42 | ], 43 | ), 44 | body: SingleChildScrollView( 45 | child: ListBody( 46 | children: [ 47 | ListTile( 48 | title: const Text("Loading Indicator..."), 49 | trailing: NativeLoadingIndicator(), 50 | ), 51 | ListTile( 52 | title: const Text("Switch"), 53 | trailing: NativeSwitch( 54 | value: _active, 55 | onChanged: (bool value) => setState(() => _active = value), 56 | ), 57 | ), 58 | // Container( 59 | // padding: EdgeInsets.all(12.0), 60 | // child: NativeTextInput( 61 | // leading: Icon(Icons.person), 62 | // decoration: InputDecoration(labelText: "Input Placeholder"), 63 | // // trailing: Icon(Icons.help), 64 | // ), 65 | // ), 66 | Container(height: 20.0), 67 | NativeGroupSelect( 68 | groupValue: _selected, 69 | children: { 70 | 0: Text('Midnight'), 71 | 1: Text('Viridian'), 72 | 2: Text('Cerulean'), 73 | }, 74 | onValueChanged: (int value) { 75 | setState(() { 76 | _selected = value; 77 | }); 78 | }, 79 | ), 80 | NativeSelection( 81 | value: _value, 82 | items: [ 83 | "Apple", 84 | "Orange", 85 | "Pineapple", 86 | "Cherry", 87 | ], 88 | onChanged: (String value) { 89 | setState(() { 90 | _value = value; 91 | }); 92 | }, 93 | ), 94 | NativeListTile( 95 | title: const Text("Power Saver"), 96 | // subtitle: Text("Puts Device into Low Power Mode"), 97 | // hideLeadingIcon: true, 98 | ios: CupertinoListTileData( 99 | style: CupertinoCellStyle.basic, 100 | ), 101 | trailing: [ 102 | NativeSwitch( 103 | value: _switch, 104 | onChanged: (bool value) { 105 | setState(() { 106 | _switch = value; 107 | }); 108 | }), 109 | ], 110 | ), 111 | Container( 112 | padding: const EdgeInsets.all(20.0), 113 | child: NativeButton( 114 | child: const Text("Submit"), 115 | // padding: const EdgeInsets.all(20.0), 116 | color: Colors.blue, 117 | onPressed: () => showAlertPopup(context, 118 | title: "Native Dialog", detail: "Button Submitted!"), 119 | ), 120 | ), 121 | ], 122 | ), 123 | ), 124 | ); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /example/lib/utils/pop_up.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:native_widgets/native_widgets.dart'; 3 | 4 | Future showAlertPopup(BuildContext context, 5 | {String title, String detail}) async { 6 | return showNativeDialog( 7 | context: context, 8 | child: NativeDialog( 9 | title: Text(title), 10 | content: Text(detail), 11 | actions: [ 12 | NativeDialogAction( 13 | text: Text('Delete'), 14 | isDestructive: true, 15 | onPressed: () { 16 | Navigator.of(context, rootNavigator: true).pop(true); 17 | }), 18 | NativeDialogAction( 19 | text: Text('Ok'), 20 | isDestructive: false, 21 | removeInActionSheet: true, 22 | onPressed: () { 23 | Navigator.of(context, rootNavigator: true).pop(); 24 | }), 25 | ], 26 | ios: CupertinoDialogData( 27 | showActionSheet: false, 28 | cancelButton: CupertinoActionSheetAction( 29 | child: const Text('Cancel'), 30 | isDefaultAction: true, 31 | onPressed: () { 32 | Navigator.of(context, rootNavigator: true).pop(); 33 | }, 34 | ), 35 | ), 36 | )); 37 | } 38 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/macos/Flutter/ephemeral/Flutter-Generated.xcconfig: -------------------------------------------------------------------------------- 1 | // This is a generated file; do not edit or check into version control. 2 | FLUTTER_ROOT=/usr/local/Caskroom/flutter/1.2.1/flutter 3 | FLUTTER_APPLICATION_PATH=/Users/rodydavis/Developer/GitHub/plugins/packages/native_widgets/example 4 | COCOAPODS_PARALLEL_CODE_SIGN=true 5 | FLUTTER_BUILD_DIR=build 6 | FLUTTER_BUILD_NAME=1.0.0 7 | FLUTTER_BUILD_NUMBER=1 8 | EXCLUDED_ARCHS=arm64 9 | DART_OBFUSCATION=false 10 | TRACK_WIDGET_CREATION=false 11 | TREE_SHAKE_ICONS=false 12 | PACKAGE_CONFIG=.packages 13 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2020 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "2.1.1" 53 | crypto: 54 | dependency: transitive 55 | description: 56 | name: crypto 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.1.5" 60 | cupertino_icons: 61 | dependency: "direct main" 62 | description: 63 | name: cupertino_icons 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.1.3" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.0" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_list_drag_and_drop: 80 | dependency: transitive 81 | description: 82 | name: flutter_list_drag_and_drop 83 | url: "https://pub.dartlang.org" 84 | source: hosted 85 | version: "0.1.6" 86 | flutter_localizations: 87 | dependency: transitive 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | flutter_platform_widgets: 92 | dependency: transitive 93 | description: 94 | name: flutter_platform_widgets 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.32.5" 98 | flutter_slidable: 99 | dependency: transitive 100 | description: 101 | name: flutter_slidable 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.5.7" 105 | flutter_sticky_header: 106 | dependency: transitive 107 | description: 108 | name: flutter_sticky_header 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "0.4.6" 112 | flutter_test: 113 | dependency: "direct dev" 114 | description: flutter 115 | source: sdk 116 | version: "0.0.0" 117 | intl: 118 | dependency: transitive 119 | description: 120 | name: intl 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "0.17.0" 124 | matcher: 125 | dependency: transitive 126 | description: 127 | name: matcher 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "0.12.10" 131 | meta: 132 | dependency: transitive 133 | description: 134 | name: meta 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.7.0" 138 | native_widgets: 139 | dependency: "direct dev" 140 | description: 141 | path: ".." 142 | relative: true 143 | source: path 144 | version: "1.3.7+1" 145 | path: 146 | dependency: transitive 147 | description: 148 | name: path 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "1.8.0" 152 | sky_engine: 153 | dependency: transitive 154 | description: flutter 155 | source: sdk 156 | version: "0.0.99" 157 | source_span: 158 | dependency: transitive 159 | description: 160 | name: source_span 161 | url: "https://pub.dartlang.org" 162 | source: hosted 163 | version: "1.8.1" 164 | stack_trace: 165 | dependency: transitive 166 | description: 167 | name: stack_trace 168 | url: "https://pub.dartlang.org" 169 | source: hosted 170 | version: "1.10.0" 171 | stream_channel: 172 | dependency: transitive 173 | description: 174 | name: stream_channel 175 | url: "https://pub.dartlang.org" 176 | source: hosted 177 | version: "2.1.0" 178 | string_scanner: 179 | dependency: transitive 180 | description: 181 | name: string_scanner 182 | url: "https://pub.dartlang.org" 183 | source: hosted 184 | version: "1.1.0" 185 | term_glyph: 186 | dependency: transitive 187 | description: 188 | name: term_glyph 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "1.2.0" 192 | test_api: 193 | dependency: transitive 194 | description: 195 | name: test_api 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "0.4.2" 199 | typed_data: 200 | dependency: transitive 201 | description: 202 | name: typed_data 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "1.3.0" 206 | uuid: 207 | dependency: transitive 208 | description: 209 | name: uuid 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "2.2.2" 213 | value_layout_builder: 214 | dependency: transitive 215 | description: 216 | name: value_layout_builder 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "0.1.0" 220 | vector_math: 221 | dependency: transitive 222 | description: 223 | name: vector_math 224 | url: "https://pub.dartlang.org" 225 | source: hosted 226 | version: "2.1.0" 227 | sdks: 228 | dart: ">=2.12.0 <3.0.0" 229 | flutter: ">=1.17.0" 230 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: native_widgets_example 2 | description: Demonstrates how to use the native_widgets plugin. 3 | 4 | environment: 5 | sdk: '>=2.10.0 <3.0.0' 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | cupertino_icons: ^0.1.0 11 | 12 | dev_dependencies: 13 | flutter_test: 14 | sdk: flutter 15 | 16 | native_widgets: 17 | path: ../ 18 | 19 | flutter: 20 | 21 | uses-material-design: true 22 | 23 | -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/web/favicon.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercommunity/native_widgets/1b3fc96ea1fce6ed216ec43fc07ae9b704781dea/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /lib/app/main_app.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeApp extends StatelessWidget { 4 | final bool showMaterial; 5 | final Color appBackground; 6 | final Widget home; 7 | 8 | NativeApp({ 9 | this.showMaterial = false, 10 | this.appBackground, 11 | this.home, 12 | }); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | final bool _isIos = showCupertino(showMaterial: showMaterial); 17 | if (_isIos) { 18 | return CupertinoApp( 19 | color: appBackground, 20 | home: home, 21 | ); 22 | } 23 | return MaterialApp( 24 | color: appBackground, 25 | home: home, 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/app_bar/app_bar.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // Native App Bar 4 | class NativeAppBar extends StatelessWidget implements PreferredSizeWidget { 5 | final Color backgroundColor; 6 | // final Color foregroundColor; 7 | final Widget leading; 8 | final Widget title; 9 | final List actions; 10 | // final List tabs; 11 | // final bool showMaterial; 12 | // final ValueChanged onValueChanged; 13 | // final dynamic groupValue; 14 | final bool automaticallyImplyLeading; 15 | final MaterialAppBarData android; 16 | final CupertinoNavigationBarData ios; 17 | 18 | // final TabBar bottom; 19 | 20 | NativeAppBar({ 21 | Key key, 22 | // this.foregroundColor, 23 | this.backgroundColor, 24 | this.leading, 25 | this.title, 26 | this.actions, 27 | // this.tabs, 28 | // this.showMaterial = false, 29 | this.preferredSize = const Size.fromHeight(56.0), 30 | // this.groupValue, 31 | // this.onValueChanged, 32 | this.automaticallyImplyLeading, 33 | this.ios, 34 | this.android, 35 | }); 36 | 37 | @override 38 | final Size preferredSize; 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | // final bool _isIos = showCupertino(showMaterial: showMaterial); 43 | // final Map iosTabs = const {}; 44 | 45 | // if (tabs != null && tabs.isNotEmpty) { 46 | // int _index = 0; 47 | // for (Widget item in tabs) { 48 | // iosTabs[_index] = item; 49 | // } 50 | // _index++; 51 | // } 52 | 53 | // if (_isIos) { 54 | // return CupertinoNavigationBar( 55 | // middle: tabs == null || tabs.length < 2 56 | // ? title 57 | // : CupertinoSegmentedControl( 58 | // onValueChanged: onValueChanged, 59 | // children: iosTabs, 60 | // groupValue: groupValue, 61 | // ), 62 | // backgroundColor: 63 | // backgroundColor == null ? Colors.transparent : backgroundColor, 64 | // leading: leading, 65 | // actionsForegroundColor: foregroundColor, 66 | // trailing: actions == null 67 | // ? null 68 | // : Row( 69 | // mainAxisAlignment: MainAxisAlignment.end, 70 | // mainAxisSize: MainAxisSize.min, 71 | // crossAxisAlignment: CrossAxisAlignment.end, 72 | // children: actions.map((Widget item) => item).toList(), 73 | // ), 74 | // ); 75 | // } 76 | 77 | // return AppBar( 78 | // backgroundColor: backgroundColor, 79 | // key: key, 80 | // title: title, 81 | // actions: actions, 82 | // leading: leading, 83 | // bottom: tabs == null ? null : TabBar(tabs: tabs), 84 | // ); 85 | return PlatformAppBar( 86 | key: key, 87 | backgroundColor: backgroundColor, 88 | title: title, 89 | trailingActions: actions, 90 | leading: leading, 91 | automaticallyImplyLeading: automaticallyImplyLeading, 92 | ios: (BuildContext context) => ios, 93 | android: (BuildContext context) => android, 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/app_bar/cupertino/search.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../common/search/cupertino_search_bar.dart'; 3 | 4 | class CupertinoSearchWidget extends StatefulWidget { 5 | final TextStyle searchText; 6 | final Color searchBackground, searchIconColor, searchCursorColor; 7 | final ValueChanged onChanged; 8 | // final ValueChanged onSearching; 9 | final VoidCallback onCancel, onSearch; 10 | final String initialValue; 11 | final bool alwaysShowAppBar; 12 | 13 | const CupertinoSearchWidget({ 14 | this.searchBackground, 15 | this.searchCursorColor, 16 | this.searchIconColor, 17 | this.searchText, 18 | this.onChanged, 19 | this.initialValue, 20 | this.alwaysShowAppBar = false, 21 | this.onCancel, 22 | this.onSearch, 23 | // this.isSearching = false, 24 | }); 25 | 26 | @override 27 | CupertinoSearchBarState createState() { 28 | return new CupertinoSearchBarState(); 29 | } 30 | } 31 | 32 | class CupertinoSearchBarState extends State 33 | with SingleTickerProviderStateMixin { 34 | TextStyle searchText; 35 | Color searchBackground, searchIconColor, searchCursorColor; 36 | 37 | TextEditingController _searchTextController; 38 | FocusNode _searchFocusNode = new FocusNode(); 39 | Animation _animation; 40 | AnimationController _animationController; 41 | 42 | @override 43 | void initState() { 44 | _searchTextController = TextEditingController(text: widget.initialValue); 45 | 46 | _animationController = new AnimationController( 47 | duration: new Duration(milliseconds: 200), 48 | vsync: this, 49 | ); 50 | _animation = new CurvedAnimation( 51 | parent: _animationController, 52 | curve: Curves.easeInOut, 53 | reverseCurve: Curves.easeInOut, 54 | ); 55 | _searchFocusNode.addListener(() { 56 | if (!_animationController.isAnimating) { 57 | _animationController.forward(); 58 | } 59 | // if (_searchFocusNode.hasFocus) { 60 | // _animationController.forward(); 61 | // } else { 62 | // _animationController.reverse(); 63 | // } 64 | }); 65 | if (!widget.alwaysShowAppBar) { 66 | _startSearch(); 67 | } 68 | super.initState(); 69 | } 70 | 71 | void _startSearch() { 72 | _searchTextController.clear(); 73 | _animationController.forward(); 74 | } 75 | 76 | void _cancelSearch() { 77 | if (widget.alwaysShowAppBar) { 78 | _searchTextController.clear(); 79 | _searchFocusNode.unfocus(); 80 | _animationController.reverse(); 81 | } 82 | if (widget?.onCancel != null) widget.onCancel(); 83 | } 84 | 85 | void _clearSearch() { 86 | _searchTextController.clear(); 87 | widget?.onChanged(""); 88 | } 89 | 90 | @override 91 | void dispose() { 92 | _animationController.dispose(); 93 | _searchFocusNode.dispose(); 94 | _searchTextController.dispose(); 95 | super.dispose(); 96 | } 97 | 98 | @override 99 | Widget build(BuildContext context) { 100 | if (!widget.alwaysShowAppBar) 101 | FocusScope.of(context).requestFocus(_searchFocusNode); 102 | 103 | return new CupertinoSearchBar( 104 | controller: _searchTextController, 105 | focusNode: _searchFocusNode, 106 | animation: _animation, 107 | onCancel: _cancelSearch, 108 | onClear: _clearSearch, 109 | autoFocus: false, 110 | ); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /lib/app_bar/search_bar.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeSearchAppBar extends StatelessWidget 4 | implements PreferredSizeWidget { 5 | final bool isSearching; 6 | final bool alwaysShowSearchBar; 7 | final String search; 8 | final Widget leading, title; 9 | final List actions; 10 | final ValueChanged onChanged; 11 | final VoidCallback onSearchPressed; 12 | final MaterialAppBarData android; 13 | final CupertinoNavigationBarData ios; 14 | final Color backgroundColor; 15 | 16 | NativeSearchAppBar({ 17 | this.isSearching = false, 18 | this.onChanged, 19 | this.ios, 20 | this.android, 21 | this.onSearchPressed, 22 | this.search, 23 | this.leading, 24 | this.title, 25 | this.actions, 26 | this.backgroundColor, 27 | this.alwaysShowSearchBar = false, 28 | this.preferredSize = const Size.fromHeight(56.0), 29 | }); 30 | 31 | @override 32 | final Size preferredSize; 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | if (isSearching) { 37 | return PlatformAppBar( 38 | title: title, 39 | backgroundColor: backgroundColor, 40 | leading: leading, 41 | android: (BuildContext context) => MaterialAppBarData( 42 | title: MaterialSearchBar( 43 | search: search, 44 | onSearchChanged: onChanged, 45 | ), 46 | actions: [ 47 | PlatformIconButton( 48 | icon: const Icon(Icons.search), 49 | iosIcon: const Icon(CupertinoIcons.search), 50 | onPressed: onSearchPressed, 51 | ), 52 | ]), 53 | ios: (BuildContext context) => CupertinoNavigationBarData( 54 | title: CupertinoSearchWidget( 55 | initialValue: search, 56 | onChanged: onChanged, 57 | alwaysShowAppBar: alwaysShowSearchBar, 58 | onCancel: onSearchPressed, 59 | ), 60 | transitionBetweenRoutes: ios?.transitionBetweenRoutes, 61 | heroTag: ios?.heroTag, 62 | ), 63 | ); 64 | } 65 | 66 | return PlatformAppBar( 67 | backgroundColor: backgroundColor, 68 | leading: leading, 69 | title: title, 70 | trailingActions: [ 71 | IconButton( 72 | icon: const Icon(Icons.search), 73 | tooltip: 'Search', 74 | onPressed: onSearchPressed, 75 | ), 76 | ]..addAll(actions ?? []), 77 | ios: (BuildContext context) => ios, 78 | android: (BuildContext context) => android, 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/button/icon_button.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeIconButton extends StatelessWidget { 4 | final Icon icon, iosIcon; 5 | final Key widgetKey; 6 | final VoidCallback onPressed; 7 | final EdgeInsets padding; 8 | final Color color; 9 | 10 | NativeIconButton({ 11 | Key key, 12 | @required this.icon, 13 | this.iosIcon, 14 | this.onPressed, 15 | this.widgetKey, 16 | this.padding, 17 | this.color, 18 | }); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return PlatformIconButton( 23 | padding: padding, 24 | key: key, 25 | widgetKey: widgetKey, 26 | icon: icon, 27 | iosIcon: iosIcon, 28 | androidIcon: icon, 29 | onPressed: onPressed, 30 | color: color, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/button/raised_button.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // Native Button 4 | class NativeButton extends StatelessWidget { 5 | final Key widgetKey; 6 | final Widget child; 7 | final VoidCallback onPressed; 8 | final Color color, disabledColor; 9 | final EdgeInsetsGeometry padding; 10 | final CupertinoButtonData ios; 11 | final MaterialRaisedButtonData android; 12 | 13 | NativeButton({ 14 | Key key, 15 | this.widgetKey, 16 | this.child, 17 | this.onPressed, 18 | this.padding, 19 | this.color, 20 | this.disabledColor, 21 | this.ios, 22 | this.android, 23 | }); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return PlatformButton( 28 | key: key, 29 | widgetKey: widgetKey, 30 | child: child, 31 | padding: padding, 32 | color: color, 33 | disabledColor: disabledColor, 34 | onPressed: onPressed, 35 | ios: (BuildContext context) => ios, 36 | android: (BuildContext context) => android, 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/button/text_button.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeTextButton extends StatelessWidget { 4 | final VoidCallback onPressed; 5 | final String label; 6 | final CupertinoNativeTextButtonData ios; 7 | final MaterialNativeTextButtonData android; 8 | final TextStyle style; 9 | 10 | NativeTextButton({ 11 | Key key, 12 | this.onPressed, 13 | @required this.label, 14 | this.ios, 15 | this.android, 16 | this.style = const TextStyle(), 17 | }); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return PlatformWidget( 22 | key: key, 23 | ios: (BuildContext context) { 24 | if (onPressed == null) { 25 | return Text( 26 | label, 27 | style: style.copyWith(color: CupertinoColors.inactiveGray), 28 | ); 29 | } 30 | 31 | return GestureDetector( 32 | onTap: onPressed, 33 | child: Text( 34 | label, 35 | style: style.copyWith( 36 | color: ios?.activeColor ?? CupertinoColors.activeBlue, 37 | ), 38 | ), 39 | ); 40 | }, 41 | android: (BuildContext context) { 42 | return InkWell( 43 | onTap: onPressed, 44 | child: Text(label, 45 | style: style.copyWith( 46 | color: onPressed == null ? Colors.grey : android?.activeColor, 47 | )), 48 | ); 49 | }, 50 | ); 51 | } 52 | } 53 | 54 | class CupertinoNativeTextButtonData { 55 | final Color activeColor; 56 | 57 | CupertinoNativeTextButtonData({ 58 | this.activeColor = CupertinoColors.activeBlue, 59 | }); 60 | } 61 | 62 | class MaterialNativeTextButtonData { 63 | final Color activeColor; 64 | 65 | MaterialNativeTextButtonData({ 66 | this.activeColor = Colors.blue, 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /lib/common/common_tiles/avatar_title.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../native_widgets.dart'; 5 | 6 | class CupertinoAvatarListTile extends StatelessWidget { 7 | const CupertinoAvatarListTile({ 8 | @required this.title, 9 | this.subtitle, 10 | this.actions, 11 | this.avatar, 12 | }); 13 | 14 | final Widget avatar; 15 | final String title, subtitle; 16 | final List actions; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | final List _widgets = [ 21 | Container( 22 | height: 60.0, 23 | width: 60.0, 24 | child: avatar, 25 | ), 26 | Expanded( 27 | child: Padding( 28 | padding: const EdgeInsets.symmetric(horizontal: 12.0), 29 | child: subtitle == null 30 | ? NativeText(title, type: NativeTextTheme.title) 31 | : Column( 32 | crossAxisAlignment: CrossAxisAlignment.start, 33 | children: [ 34 | NativeText(title, type: NativeTextTheme.title), 35 | NativeText(subtitle, type: NativeTextTheme.subtitle), 36 | ], 37 | ), 38 | ), 39 | ), 40 | ]; 41 | 42 | final Widget row = Container( 43 | padding: const EdgeInsets.only(left: 8.0), 44 | child: Row( 45 | children: _widgets..addAll(actions ?? []), 46 | ), 47 | ); 48 | 49 | return row; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/common/common_tiles/base_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../native_widgets.dart'; 5 | 6 | class CupertinoBaseTile extends StatelessWidget { 7 | const CupertinoBaseTile({ 8 | this.selected = false, 9 | this.editing = false, 10 | @required this.child, 11 | this.accessory = CupertinoAccessory.none, 12 | this.editingAccessory = CupertinoEditingAccessory.none, 13 | this.editingAction = CupertinoEditingAction.remove, 14 | this.accessoryTap, 15 | this.onLongPressed, 16 | this.onTap, 17 | this.editingAccessoryTap, 18 | this.editingActionTap, 19 | this.padding, 20 | }); 21 | 22 | final bool editing, selected; 23 | final Widget child; 24 | final EdgeInsets padding; 25 | final CupertinoEditingAction editingAction; 26 | final CupertinoEditingAccessory editingAccessory; 27 | final CupertinoAccessory accessory; 28 | final VoidCallback accessoryTap, 29 | onTap, 30 | onLongPressed, 31 | editingAccessoryTap, 32 | editingActionTap; 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | final List _widgets = []; 37 | 38 | if (editing) { 39 | if (editingAccessory != null) 40 | switch (editingAccessory) { 41 | case CupertinoEditingAccessory.disclosureIndicator: 42 | _widgets 43 | ..add( 44 | const Icon(CupertinoIcons.right_chevron), 45 | ); 46 | break; 47 | case CupertinoEditingAccessory.detailDisclosure: 48 | _widgets 49 | ..addAll([ 50 | IconButton( 51 | icon: const Icon(CupertinoIcons.info, 52 | color: CupertinoColors.activeBlue), 53 | onPressed: editingAccessoryTap, 54 | ), 55 | const Icon(CupertinoIcons.right_chevron), 56 | ]); 57 | break; 58 | case CupertinoEditingAccessory.detail: 59 | _widgets 60 | ..add( 61 | IconButton( 62 | icon: const Icon(CupertinoIcons.info, 63 | color: CupertinoColors.activeBlue), 64 | onPressed: editingAccessoryTap, 65 | ), 66 | ); 67 | break; 68 | case CupertinoEditingAccessory.checkmark: 69 | _widgets 70 | ..add( 71 | const Icon(CupertinoIcons.check_mark), 72 | ); 73 | break; 74 | case CupertinoEditingAccessory.dragHandle: 75 | _widgets 76 | ..add(IconButton( 77 | icon: const Icon(Icons.dehaze), 78 | onPressed: () {}, 79 | )); 80 | break; 81 | case CupertinoEditingAccessory.none: 82 | break; 83 | } 84 | } else { 85 | if (accessory != null) 86 | switch (accessory) { 87 | case CupertinoAccessory.disclosureIndicator: 88 | _widgets..add(const Icon(CupertinoIcons.right_chevron)); 89 | break; 90 | case CupertinoAccessory.detailDisclosure: 91 | _widgets 92 | ..addAll([ 93 | NativeIconButton( 94 | icon: const Icon(CupertinoIcons.info), 95 | onPressed: accessoryTap, 96 | ), 97 | const Icon(CupertinoIcons.right_chevron), 98 | ]); 99 | break; 100 | case CupertinoAccessory.detail: 101 | _widgets 102 | ..add(NativeIconButton( 103 | icon: const Icon(CupertinoIcons.info), 104 | onPressed: accessoryTap, 105 | )); 106 | break; 107 | case CupertinoAccessory.checkmark: 108 | _widgets..add(const Icon(CupertinoIcons.check_mark)); 109 | break; 110 | case CupertinoAccessory.none: 111 | break; 112 | } 113 | } 114 | 115 | Widget _editingAction; 116 | 117 | if (editingAction != null) { 118 | switch (editingAction) { 119 | case CupertinoEditingAction.remove: 120 | _editingAction = Container( 121 | height: 25.0, 122 | width: 25.0, 123 | decoration: BoxDecoration( 124 | color: Colors.red, 125 | borderRadius: BorderRadius.circular(25.0), 126 | ), 127 | child: NativeIconButton( 128 | icon: Icon( 129 | Icons.remove, 130 | color: CupertinoColors.white, 131 | // size: 18.0, 132 | ), 133 | onPressed: editingActionTap, 134 | ), 135 | ); 136 | break; 137 | case CupertinoEditingAction.select: 138 | _editingAction = Container( 139 | height: 25.0, 140 | width: 25.0, 141 | decoration: selected 142 | ? BoxDecoration( 143 | color: CupertinoColors.activeBlue, 144 | borderRadius: BorderRadius.circular(25.0), 145 | ) 146 | : new BoxDecoration( 147 | border: new Border.all( 148 | color: CupertinoColors.lightBackgroundGray), 149 | shape: BoxShape.circle), 150 | child: NativeIconButton( 151 | icon: Icon( 152 | CupertinoIcons.check_mark, 153 | color: selected ? CupertinoColors.white : Colors.transparent, 154 | ), 155 | onPressed: editingActionTap, 156 | ), 157 | ); 158 | break; 159 | case CupertinoEditingAction.none: 160 | _editingAction = null; 161 | break; 162 | } 163 | } 164 | 165 | Color _rowColor = Colors.transparent; 166 | 167 | if (selected && editing) { 168 | _rowColor = Colors.lightBlue[50]; 169 | } 170 | 171 | if (!editing && selected) { 172 | _rowColor = Colors.lightBlue[50]; 173 | } 174 | 175 | final Widget row = GestureDetector( 176 | behavior: HitTestBehavior.opaque, 177 | onTap: onTap, 178 | onLongPress: onLongPressed, 179 | child: SafeArea( 180 | top: false, 181 | bottom: false, 182 | child: Container( 183 | color: _rowColor, 184 | padding: padding, 185 | child: Row( 186 | children: [ 187 | Container( 188 | padding: editing && _editingAction != null 189 | ? const EdgeInsets.only(left: 12.0) 190 | : null, 191 | child: editing ? _editingAction : null, 192 | ), 193 | Expanded(child: child), 194 | ]..addAll(_widgets ?? []), 195 | ), 196 | ), 197 | ), 198 | ); 199 | 200 | return row; 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /lib/common/common_tiles/basic_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CupertinoTextMenu extends StatelessWidget { 4 | final bool lastItem; 5 | final List children; 6 | 7 | CupertinoTextMenu({ 8 | @required this.children, 9 | this.lastItem = false, 10 | }); 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Container( 15 | decoration: const BoxDecoration( 16 | color: Colors.transparent, 17 | border: Border( 18 | top: BorderSide(color: Color(0xFFBCBBC1), width: 0.0), 19 | bottom: BorderSide(color: Color(0xFFBCBBC1), width: 0.0), 20 | ), 21 | ), 22 | height: 44.0, 23 | child: Padding( 24 | padding: const EdgeInsets.symmetric(horizontal: 16.0), 25 | child: SafeArea( 26 | top: false, 27 | bottom: false, 28 | child: Row( 29 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 30 | children: children, 31 | ), 32 | ), 33 | ), 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/common/common_tiles/phone_tile.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../native_widgets.dart'; 5 | 6 | class CupertinoPhoneListTile extends StatelessWidget { 7 | final String subtitle, title; 8 | final List actions; 9 | final NativeIcon icon; 10 | final bool hideLeadingIcon; 11 | 12 | const CupertinoPhoneListTile({ 13 | this.actions, 14 | this.subtitle, 15 | @required this.title, 16 | this.icon, 17 | this.hideLeadingIcon = true, 18 | }); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | Widget row; 23 | if (subtitle == null) { 24 | row = Container( 25 | // color: selected ? Colors.grey[400] : Colors.transparent, 26 | height: 40.0, 27 | padding: EdgeInsets.only(top: subtitle == null ? 0.0 : 9.0), 28 | child: Row( 29 | children: [ 30 | Container( 31 | width: hideLeadingIcon ? 12.0 : 38.0, 32 | child: icon != null && !hideLeadingIcon 33 | ? Align( 34 | alignment: Alignment.center, 35 | child: icon?.iosIcon != null 36 | ? Icon( 37 | icon.iosIcon, 38 | color: CupertinoColors.inactiveGray, 39 | size: 18.0, 40 | ) 41 | : icon, 42 | ) 43 | : null, 44 | ), 45 | Expanded( 46 | child: Container( 47 | padding: 48 | const EdgeInsets.only(left: 1.0, bottom: 0.0, right: 10.0), 49 | child: Row( 50 | children: [ 51 | Expanded( 52 | child: Column( 53 | crossAxisAlignment: CrossAxisAlignment.start, 54 | mainAxisAlignment: MainAxisAlignment.center, 55 | children: [ 56 | NativeText(title, type: NativeTextTheme.title) 57 | ], 58 | ), 59 | ), 60 | ]..addAll(actions ?? [])), 61 | ), 62 | ), 63 | ], 64 | ), 65 | ); 66 | } else { 67 | row = Container( 68 | // color: selected ? Colors.grey[400] : Colors.transparent, 69 | height: 60.0, 70 | padding: const EdgeInsets.only(top: 9.0), 71 | child: Row( 72 | children: [ 73 | Container( 74 | width: hideLeadingIcon ? 12.0 : 38.0, 75 | child: icon != null && !hideLeadingIcon 76 | ? Align( 77 | alignment: Alignment.topCenter, 78 | child: icon?.iosIcon != null 79 | ? Icon( 80 | icon.iosIcon, 81 | color: CupertinoColors.inactiveGray, 82 | size: 18.0, 83 | ) 84 | : icon, 85 | ) 86 | : null, 87 | ), 88 | Expanded( 89 | child: Container( 90 | padding: 91 | const EdgeInsets.only(left: 1.0, bottom: 9.0, right: 10.0), 92 | child: Row( 93 | children: [ 94 | Expanded( 95 | child: Column( 96 | crossAxisAlignment: CrossAxisAlignment.start, 97 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 98 | children: [ 99 | NativeText(title, type: NativeTextTheme.title), 100 | NativeText(subtitle, type: NativeTextTheme.subtitle), 101 | ], 102 | ), 103 | ), 104 | ]..addAll(actions ?? [])), 105 | ), 106 | ), 107 | ], 108 | ), 109 | ); 110 | } 111 | 112 | return row; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/common/list_tile.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeListTile extends StatelessWidget { 4 | final Text subtitle, title, id; 5 | final Widget avatar, child; 6 | final List trailing; 7 | final NativeIcon leading; 8 | final MaterialListTileData android; 9 | final CupertinoListTileData ios; 10 | VoidCallback onTap, onLongPressed; 11 | bool selected, editing; 12 | final bool lastItem; 13 | 14 | NativeListTile({ 15 | this.title, 16 | this.id, 17 | this.subtitle, 18 | this.leading, 19 | this.trailing, 20 | this.android, 21 | this.avatar, 22 | this.onTap, 23 | this.onLongPressed, 24 | this.ios, 25 | this.child, 26 | this.lastItem = true, 27 | this.selected = false, 28 | this.editing = false, 29 | }); 30 | // : assert(ios?.style == CupertinoCellStyle.custom && child != null); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return PlatformWidget( 35 | android: (BuildContext context) { 36 | return ListTile( 37 | onTap: onTap, 38 | onLongPress: onLongPressed, 39 | leading: avatar ?? leading, 40 | title: title, 41 | subtitle: subtitle != null ? subtitle : null, 42 | trailing: trailing != null 43 | ? SizedBox( 44 | width: 200.0, 45 | child: ButtonBar(children: trailing ?? []), 46 | ) 47 | : null, 48 | ); 49 | }, 50 | ios: (BuildContext context) { 51 | Widget _child = Container(); 52 | 53 | switch (ios?.style) { 54 | case CupertinoCellStyle.avatarDetail: 55 | _child = CupertinoAvatarListTile( 56 | avatar: avatar, 57 | title: title?.data, 58 | subtitle: subtitle?.data, 59 | actions: trailing, 60 | ); 61 | break; 62 | case CupertinoCellStyle.subtitle: 63 | _child = CupertinoPhoneListTile( 64 | title: title?.data, 65 | subtitle: subtitle?.data, 66 | actions: trailing, 67 | icon: leading, 68 | hideLeadingIcon: ios?.hideLeadingIcon, 69 | ); 70 | break; 71 | case CupertinoCellStyle.basic: 72 | _child = CupertinoTextMenu( 73 | children: [title]..addAll(trailing ?? []), 74 | ); 75 | break; 76 | 77 | case CupertinoCellStyle.leftDetail: 78 | _child = Row( 79 | children: [subtitle, title], 80 | ); 81 | break; 82 | case CupertinoCellStyle.rightDetail: 83 | _child = CupertinoTextMenu( 84 | children: [title, subtitle], 85 | ); 86 | break; 87 | case CupertinoCellStyle.custom: 88 | _child = child ?? Container(); 89 | break; 90 | } 91 | 92 | final Widget _row = CupertinoBaseTile( 93 | selected: selected, 94 | onTap: onTap, 95 | onLongPressed: onLongPressed, 96 | accessory: ios?.accessory, 97 | editing: editing, 98 | editingAccessory: ios?.editingAccessory, 99 | editingAction: ios?.editingAction, 100 | accessoryTap: ios?.accessoryTap, 101 | editingAccessoryTap: ios?.editingAccessoryTap, 102 | editingActionTap: ios?.editingActionTap, 103 | child: _child, 104 | padding: ios?.padding, 105 | ); 106 | 107 | if (lastItem) { 108 | return _row; 109 | } 110 | 111 | return Column( 112 | children: [ 113 | _row, 114 | Container( 115 | height: 1.0, 116 | color: const Color(0xFFD9D9D9), 117 | ), 118 | ], 119 | ); 120 | }, 121 | ); 122 | } 123 | } 124 | 125 | class MaterialListTileData {} 126 | 127 | class CupertinoListTileData { 128 | final CupertinoCellStyle style; 129 | final CupertinoEditingAction editingAction; 130 | final CupertinoEditingAccessory editingAccessory; 131 | final CupertinoAccessory accessory; 132 | final VoidCallback accessoryTap, editingAccessoryTap, editingActionTap; 133 | final bool hideLeadingIcon, enableReorder; 134 | final EdgeInsets padding; 135 | 136 | CupertinoListTileData({ 137 | this.style = CupertinoCellStyle.custom, 138 | this.accessory = CupertinoAccessory.none, 139 | this.editingAccessory = CupertinoEditingAccessory.none, 140 | this.editingAction = CupertinoEditingAction.remove, 141 | this.accessoryTap, 142 | this.hideLeadingIcon = false, 143 | this.enableReorder = true, 144 | this.editingAccessoryTap, 145 | this.editingActionTap, 146 | this.padding = const EdgeInsets.only(left: 8.0, bottom: 8.0, top: 8.0), 147 | }); 148 | } 149 | 150 | enum CupertinoCellStyle { 151 | basic, 152 | rightDetail, 153 | leftDetail, 154 | subtitle, 155 | avatarDetail, 156 | custom, 157 | } 158 | 159 | enum CupertinoEditingAction { 160 | none, 161 | remove, 162 | select, 163 | } 164 | 165 | enum CupertinoAccessory { 166 | none, 167 | disclosureIndicator, 168 | detailDisclosure, 169 | checkmark, 170 | detail 171 | } 172 | 173 | enum CupertinoEditingAccessory { 174 | none, 175 | disclosureIndicator, 176 | detailDisclosure, 177 | checkmark, 178 | detail, 179 | dragHandle 180 | } 181 | -------------------------------------------------------------------------------- /lib/common/routing.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // class NativeNavigator { 4 | // Future push(BuildContext context, 5 | // {@required String title, @required Widget page}) async { 6 | // return await Navigator.of(context).push(NativeRoute( 7 | // title: title, 8 | // builder: (BuildContext context) => page, 9 | // )); 10 | // } 11 | 12 | // void pop(BuildContext context) async { 13 | // Navigator.of(context).pop(); 14 | // } 15 | // } 16 | 17 | Route NativeRoute({ 18 | @required String title, 19 | bool fullscreenDialog = false, 20 | Function(BuildContext) builder, 21 | bool maintainState = false, 22 | RouteSettings settings, 23 | }) { 24 | if (Platform.isIOS || Platform.isMacOS) { 25 | return CupertinoPageRoute( 26 | title: title ?? "", 27 | builder: builder, 28 | fullscreenDialog: fullscreenDialog, 29 | maintainState: maintainState, 30 | settings: settings, 31 | ); 32 | } 33 | 34 | return MaterialPageRoute( 35 | builder: builder, 36 | fullscreenDialog: fullscreenDialog, 37 | maintainState: maintainState, 38 | settings: settings, 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /lib/common/search/cupertino_search_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/cupertino.dart'; 3 | 4 | class CupertinoSearchBar extends AnimatedWidget { 5 | const CupertinoSearchBar({ 6 | Key key, 7 | this.controller, 8 | this.focusNode, 9 | this.onCancel, 10 | this.onChanged, 11 | this.onSubmitted, 12 | this.autoFocus = false, 13 | this.animation, 14 | this.onClear, 15 | this.enabled = true, 16 | this.autoCorrect = true, 17 | }) : assert(controller != null), 18 | assert(focusNode != null), 19 | super(key: key, listenable: animation); 20 | 21 | final TextEditingController controller; 22 | final FocusNode focusNode; 23 | final ValueChanged onChanged, onSubmitted; 24 | final VoidCallback onCancel, onClear; 25 | final bool autoFocus, enabled, autoCorrect; 26 | final Animation animation; 27 | 28 | static final _opacityTween = new Tween(begin: 1.0, end: 0.0); 29 | static final _paddingTween = new Tween(begin: 0.0, end: 60.0); 30 | static final _kFontSize = 13.0; 31 | // static final Key _inputKey = new Key(debugLabel: 'searchBox'); 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | // if (!widget.alwaysShowAppBar) 36 | // FocusScope.of(context).requestFocus(_searchFocusNode); 37 | 38 | return new Padding( 39 | padding: const EdgeInsets.fromLTRB(10.0, 0.0, 20.0, 0.0), 40 | child: new Row( 41 | children: [ 42 | new Expanded( 43 | child: new Container( 44 | padding: 45 | const EdgeInsets.symmetric(horizontal: 8.0, vertical: 6.0), 46 | decoration: new BoxDecoration( 47 | color: CupertinoColors.lightBackgroundGray, 48 | border: 49 | new Border.all(width: 0.0, color: CupertinoColors.white), 50 | borderRadius: new BorderRadius.circular(10.0), 51 | ), 52 | child: new Stack( 53 | alignment: Alignment.centerLeft, 54 | children: [ 55 | new Row( 56 | mainAxisAlignment: MainAxisAlignment.start, 57 | children: [ 58 | new Padding( 59 | padding: const EdgeInsets.fromLTRB(0.0, 0.0, 4.0, 1.0), 60 | child: new Icon( 61 | CupertinoIcons.search, 62 | color: CupertinoColors.inactiveGray, 63 | size: _kFontSize + 2.0, 64 | ), 65 | ), 66 | new Text( 67 | 'Search', 68 | style: new TextStyle( 69 | inherit: false, 70 | color: CupertinoColors.inactiveGray 71 | .withOpacity(_opacityTween.evaluate(animation)), 72 | fontSize: _kFontSize, 73 | ), 74 | ), 75 | ], 76 | ), 77 | new Row( 78 | mainAxisAlignment: MainAxisAlignment.end, 79 | mainAxisSize: MainAxisSize.min, 80 | children: [ 81 | new Expanded( 82 | child: new Padding( 83 | padding: const EdgeInsets.only(left: 20.0), 84 | child: enabled 85 | ? new EditableText( 86 | key: Key("Search_Input_Box"), 87 | controller: controller, 88 | focusNode: focusNode, 89 | onChanged: onChanged, 90 | autofocus: autoFocus, 91 | onSubmitted: onSubmitted, 92 | style: new TextStyle( 93 | color: CupertinoColors.black, 94 | inherit: false, 95 | fontSize: _kFontSize, 96 | ), 97 | autocorrect: autoCorrect, 98 | cursorColor: CupertinoColors.black, 99 | backgroundCursorColor: Colors.grey, 100 | ) 101 | : null, 102 | ), 103 | ), 104 | new CupertinoButton( 105 | minSize: 10.0, 106 | padding: const EdgeInsets.all(1.0), 107 | borderRadius: new BorderRadius.circular(30.0), 108 | color: CupertinoColors.inactiveGray.withOpacity( 109 | 1.0 - _opacityTween.evaluate(animation), 110 | ), 111 | child: new Icon( 112 | Icons.close, 113 | size: 8.0, 114 | color: CupertinoColors.white, 115 | ), 116 | onPressed: () { 117 | if (animation.isDismissed) 118 | return; 119 | else 120 | onClear(); 121 | }, 122 | ), 123 | ], 124 | ), 125 | ], 126 | ), 127 | ), 128 | ), 129 | new SizedBox( 130 | width: _paddingTween.evaluate(animation), 131 | child: new CupertinoButton( 132 | padding: const EdgeInsets.only(left: 8.0), 133 | onPressed: onCancel, 134 | child: new Text( 135 | 'Cancel', 136 | softWrap: false, 137 | style: new TextStyle( 138 | inherit: false, 139 | color: CupertinoColors.activeBlue, 140 | fontSize: _kFontSize, 141 | ), 142 | ), 143 | ), 144 | ), 145 | ], 146 | ), 147 | ); 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /lib/common/search/material_search_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class MaterialSearchBar extends StatelessWidget { 4 | final TextEditingController controller; 5 | final FocusNode focusNode; 6 | final String search, name; 7 | 8 | final bool isSearching, autoFocus, autoCorrect; 9 | 10 | final Function(String) onSearchChanged; 11 | 12 | const MaterialSearchBar({ 13 | Key key, 14 | this.controller, 15 | this.focusNode, 16 | this.search, 17 | this.name, 18 | this.onSearchChanged, 19 | this.isSearching = false, 20 | this.autoFocus = false, 21 | this.autoCorrect = true, 22 | }) : assert(controller != null), 23 | assert(focusNode != null), 24 | super(key: key); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | var title = name ?? "search".toString(); 29 | var _theme = Theme.of(context); 30 | 31 | if (isSearching) { 32 | return Container( 33 | padding: const EdgeInsets.only(left: 8.0), 34 | height: 38.0, 35 | margin: EdgeInsets.only(bottom: 2.0), 36 | decoration: BoxDecoration( 37 | color: _theme?.scaffoldBackgroundColor, 38 | borderRadius: BorderRadius.circular(6.0), 39 | ), 40 | child: TextField( 41 | controller: controller, 42 | focusNode: focusNode, 43 | decoration: InputDecoration( 44 | prefixIcon: Padding( 45 | padding: EdgeInsets.only(right: 8.0), 46 | child: Icon(Icons.search), 47 | ), 48 | border: InputBorder.none, 49 | hintText: 'Search'), 50 | autofocus: autoFocus, 51 | autocorrect: autoCorrect, 52 | onChanged: (String value) => onSearchChanged(value), 53 | ), 54 | ); 55 | } 56 | 57 | return Text(title); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/common/search/native_search.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeSearchWidget extends AnimatedWidget { 4 | final String search; 5 | final bool isSearching; 6 | final TextEditingController controller; 7 | final FocusNode focusNode; 8 | final ValueChanged onChanged, onSubmitted; 9 | final VoidCallback onCancel, onClear; 10 | final bool autoFocus, enabled; 11 | final Animation animation; 12 | 13 | const NativeSearchWidget({ 14 | Key key, 15 | this.onChanged, 16 | this.search, 17 | this.onCancel, 18 | this.isSearching = false, 19 | this.onClear, 20 | this.animation, 21 | this.onSubmitted, 22 | this.autoFocus = false, 23 | this.focusNode, 24 | this.controller, 25 | this.enabled = true, 26 | }) : assert(controller != null), 27 | assert(focusNode != null), 28 | super(key: key, listenable: animation); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return PlatformWidget( 33 | android: (BuildContext context) => MaterialSearchBar( 34 | search: search, 35 | isSearching: isSearching, 36 | onSearchChanged: onChanged, 37 | ), 38 | ios: (BuildContext context) => CupertinoSearchBar( 39 | enabled: enabled, 40 | onChanged: onChanged, 41 | onCancel: onCancel, 42 | onClear: onClear, 43 | onSubmitted: onSubmitted, 44 | animation: animation, 45 | controller: controller, 46 | autoFocus: autoFocus, 47 | focusNode: focusNode, 48 | ), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/common/text.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | enum NativeTextTheme { title, subtitle, detail, custom } 4 | 5 | class NativeText extends StatelessWidget { 6 | final String data; 7 | final TextStyle style; 8 | final int maxLines; 9 | final NativeTextTheme type; 10 | 11 | const NativeText( 12 | this.data, { 13 | Key key, 14 | this.style, 15 | this.maxLines = 1, 16 | this.type = NativeTextTheme.detail, 17 | }); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return PlatformWidget( 22 | key: key, 23 | android: (BuildContext context) { 24 | switch (type) { 25 | case NativeTextTheme.title: 26 | return Text( 27 | data, 28 | maxLines: 1, 29 | overflow: TextOverflow.ellipsis, 30 | style: Theme.of(context).textTheme.title, 31 | ); 32 | case NativeTextTheme.subtitle: 33 | return Text( 34 | data, 35 | maxLines: 1, 36 | overflow: TextOverflow.ellipsis, 37 | style: Theme.of(context).textTheme.subtitle, 38 | ); 39 | case NativeTextTheme.detail: 40 | return Text( 41 | data, 42 | style: Theme.of(context).textTheme.caption, 43 | ); 44 | case NativeTextTheme.custom: 45 | return Text( 46 | data, 47 | style: style ?? Theme.of(context).textTheme.title, 48 | ); 49 | } 50 | return Text( 51 | data, 52 | maxLines: maxLines, 53 | style: style, 54 | ); 55 | }, 56 | ios: (BuildContext context) { 57 | switch (type) { 58 | case NativeTextTheme.title: 59 | return Text( 60 | data, 61 | maxLines: 1, 62 | overflow: TextOverflow.ellipsis, 63 | style: const TextStyle( 64 | fontWeight: FontWeight.w600, 65 | letterSpacing: -0.18, 66 | ), 67 | ); 68 | case NativeTextTheme.subtitle: 69 | return Text( 70 | data, 71 | maxLines: 1, 72 | overflow: TextOverflow.ellipsis, 73 | style: const TextStyle( 74 | fontSize: 15.0, 75 | letterSpacing: -0.24, 76 | color: CupertinoColors.inactiveGray, 77 | ), 78 | ); 79 | case NativeTextTheme.detail: 80 | return Text( 81 | data, 82 | style: const TextStyle( 83 | color: CupertinoColors.inactiveGray, 84 | fontSize: 15.0, 85 | letterSpacing: -0.41, 86 | ), 87 | ); 88 | case NativeTextTheme.custom: 89 | return Text( 90 | data, 91 | style: style ?? 92 | const TextStyle( 93 | color: CupertinoColors.inactiveGray, 94 | fontSize: 15.0, 95 | letterSpacing: -0.41, 96 | ), 97 | ); 98 | } 99 | }, 100 | ); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /lib/common/widget.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeWidget extends StatelessWidget { 4 | final Widget android, ios, windows, fuchsia, macos, linux, child; 5 | // final PlatformBuilder child; 6 | const NativeWidget({ 7 | Key key, 8 | this.android, 9 | this.ios, 10 | this.linux, 11 | this.fuchsia, 12 | this.macos, 13 | this.windows, 14 | @required this.child, 15 | }) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | if (Platform.isWindows) { 20 | return Container(key: key, child: windows ?? child); 21 | } else if (Platform.isFuchsia) { 22 | return Container(key: key, child: fuchsia ?? child); 23 | } else if (Platform.isMacOS) { 24 | return Container(key: key, child: macos ?? child); 25 | } else if (Platform.isLinux) { 26 | return Container(key: key, child: linux ?? child); 27 | } else if (Platform.isAndroid) { 28 | return Container(key: key, child: android ?? child); 29 | } else if (Platform.isIOS) { 30 | return Container(key: key, child: ios ?? child); 31 | } 32 | return Container(key: key, child: child); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/dialog/alert_dialog.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | Future showNativeDialog({ 4 | @required BuildContext context, 5 | @required NativeDialog child, 6 | }) { 7 | if (Platform.isIOS) { 8 | if (child?.ios?.showActionSheet ?? false) { 9 | return showCupertinoModalPopup( 10 | context: context, 11 | builder: (BuildContext context) => child, 12 | ); 13 | } else { 14 | return showCupertinoDialog( 15 | context: context, 16 | builder: (BuildContext context) => child, 17 | ); 18 | } 19 | } 20 | return showDialog( 21 | context: context, 22 | builder: (BuildContext context) => child, 23 | ); 24 | } 25 | 26 | // Native Dialog 27 | class NativeDialog extends StatelessWidget { 28 | final Text title; 29 | final Text content; 30 | final List actions; 31 | final CupertinoDialogData ios; 32 | 33 | const NativeDialog({ 34 | Key key, 35 | @required this.actions, 36 | this.title, 37 | @required this.content, 38 | this.ios, 39 | }) : super(key: key); 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return PlatformWidget( 44 | key: key, 45 | ios: (BuildContext context) { 46 | if (ios?.showActionSheet ?? false || actions.length > 3) { 47 | NativeDialogAction _toRemove; 48 | for (NativeDialogAction item in actions) { 49 | if (actions.contains(item?.removeInActionSheet ?? false)) { 50 | _toRemove = item; 51 | } 52 | } 53 | if (_toRemove != null) actions.remove(_toRemove); 54 | return CupertinoActionSheet( 55 | title: title, 56 | message: content, 57 | actions: actions 58 | .map((NativeDialogAction item) => CupertinoActionSheetAction( 59 | child: item.text, 60 | isDestructiveAction: item.isDestructive, 61 | onPressed: Feedback.wrapForTap(item.onPressed, context), 62 | )) 63 | .toList(), 64 | cancelButton: ios?.cancelButton ?? 65 | CupertinoActionSheetAction( 66 | child: const Text('Cancel'), 67 | isDefaultAction: true, 68 | onPressed: () { 69 | Navigator.pop(context, 'Cancel'); 70 | }, 71 | ), 72 | ); 73 | } 74 | 75 | // actions.add(cancelAction); 76 | return CupertinoAlertDialog( 77 | title: title, 78 | content: content, 79 | actions: actions 80 | .map((NativeDialogAction item) => CupertinoDialogAction( 81 | child: item.text, 82 | isDestructiveAction: item.isDestructive, 83 | onPressed: Feedback.wrapForTap(item.onPressed, context), 84 | )) 85 | .toList()); 86 | }, 87 | android: (BuildContext context) { 88 | // actions.add(cancelAction); 89 | return AlertDialog( 90 | title: title, 91 | content: content, 92 | actions: actions 93 | .map((NativeDialogAction item) => FlatButton( 94 | child: Text( 95 | item.text?.data, 96 | style: TextStyle( 97 | color: 98 | item.isDestructive ? Colors.redAccent : null), 99 | ), 100 | onPressed: item.onPressed, 101 | )) 102 | .toList()); 103 | }); 104 | } 105 | } 106 | 107 | // Native Dialog Action for Native Dialog 108 | class NativeDialogAction { 109 | final Text text; 110 | final bool isDestructive, removeInActionSheet; 111 | final VoidCallback onPressed; 112 | 113 | const NativeDialogAction({ 114 | @required this.text, 115 | this.isDestructive, 116 | @required this.onPressed, 117 | this.removeInActionSheet = false, 118 | }); 119 | } 120 | 121 | class CupertinoDialogData { 122 | final bool showActionSheet; 123 | final CupertinoActionSheetAction cancelButton; 124 | 125 | const CupertinoDialogData({ 126 | this.showActionSheet = false, 127 | this.cancelButton, 128 | }); 129 | } 130 | -------------------------------------------------------------------------------- /lib/icon/icon.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeIcon extends StatelessWidget { 4 | final IconData iconData; 5 | final IconData iosIcon; 6 | 7 | NativeIcon(this.iconData, {Key key, this.iosIcon}); 8 | 9 | @override 10 | Widget build(BuildContext context) { 11 | return PlatformWidget( 12 | key: key, 13 | ios: (BuildContext contesxt) => Icon(iosIcon ?? iconData), 14 | android: (BuildContext contesxt) => Icon(iconData), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/input/date_picker.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeDatePicker extends StatelessWidget { 4 | NativeDatePicker({ 5 | Key key, 6 | }); 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return PlatformWidget( 11 | key: key, 12 | ios: (BuildContext context) {}, 13 | android: (BuildContext context) {}, 14 | ); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/input/group_select.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeGroupSelect extends StatelessWidget { 4 | final ValueChanged onValueChanged; 5 | final Map children; 6 | final T groupValue; 7 | 8 | NativeGroupSelect({ 9 | Key key, 10 | this.onValueChanged, 11 | @required this.groupValue, 12 | @required this.children, 13 | }); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return PlatformWidget( 18 | key: key, 19 | ios: (BuildContext context) { 20 | return CupertinoSegmentedControl( 21 | children: children, 22 | onValueChanged: onValueChanged, 23 | groupValue: groupValue, 24 | ); 25 | }, 26 | android: (BuildContext context) { 27 | return Column( 28 | children: children.entries 29 | .map((MapEntry item) => RadioListTile( 30 | title: item?.value, 31 | value: item?.key, 32 | groupValue: groupValue, 33 | onChanged: onValueChanged, 34 | )) 35 | .toList()); 36 | }, 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/input/text_field.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeTextInput extends StatelessWidget { 4 | final Widget leading, trailing; 5 | final TextEditingController controller; 6 | final TextInputType keyboardType; 7 | final TextInputAction keyboardAction; 8 | final bool autoFocus, autoCorrect, obscureText, enabled, maxLengthEnforced; 9 | final FocusNode focusNode; 10 | final TextAlign textAlign; 11 | final int maxLength, maxLines; 12 | final ValueChanged onChanged, onSubmitted; 13 | final VoidCallback onEditingComplete; 14 | final TextCapitalization textCapitalization; 15 | final InputDecoration decoration; 16 | 17 | NativeTextInput({ 18 | this.leading, 19 | this.trailing, 20 | this.controller, 21 | this.keyboardType = TextInputType.text, 22 | this.keyboardAction = TextInputAction.done, 23 | this.autoCorrect = true, 24 | this.autoFocus = false, 25 | this.obscureText = false, 26 | this.enabled = true, 27 | this.focusNode, 28 | this.textAlign = TextAlign.start, 29 | this.maxLength, 30 | this.maxLines = 1, 31 | this.maxLengthEnforced = true, 32 | this.onChanged, 33 | this.onSubmitted, 34 | this.onEditingComplete, 35 | this.textCapitalization, 36 | this.decoration, 37 | }); 38 | 39 | @override 40 | Widget build(BuildContext context) { 41 | return PlatformWidget( 42 | ios: (BuildContext context) { 43 | return CupertinoTextField( 44 | controller: controller, 45 | placeholder: decoration?.labelText ?? "", 46 | prefix: leading, 47 | suffix: trailing, 48 | clearButtonMode: OverlayVisibilityMode.editing, 49 | textInputAction: keyboardAction, 50 | keyboardType: keyboardType, 51 | autocorrect: autoCorrect, 52 | autofocus: autoFocus, 53 | textCapitalization: textCapitalization, 54 | obscureText: obscureText, 55 | enabled: enabled, 56 | focusNode: focusNode, 57 | textAlign: textAlign, 58 | maxLength: maxLength, 59 | maxLines: maxLines, 60 | maxLengthEnforced: maxLengthEnforced, 61 | onChanged: onChanged, 62 | onSubmitted: onSubmitted, 63 | onEditingComplete: onEditingComplete, 64 | ); 65 | }, 66 | android: (BuildContext context) { 67 | return ListTile( 68 | leading: leading, 69 | trailing: trailing, 70 | title: TextField( 71 | decoration: decoration, 72 | textCapitalization: textCapitalization, 73 | controller: controller, 74 | textInputAction: keyboardAction, 75 | keyboardType: keyboardType, 76 | autocorrect: autoCorrect, 77 | autofocus: autoFocus, 78 | obscureText: obscureText, 79 | enabled: enabled, 80 | focusNode: focusNode, 81 | textAlign: textAlign, 82 | maxLength: maxLength, 83 | maxLines: maxLines, 84 | maxLengthEnforced: maxLengthEnforced, 85 | onChanged: onChanged, 86 | onSubmitted: onSubmitted, 87 | onEditingComplete: onEditingComplete, 88 | ), 89 | ); 90 | }, 91 | ); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/layout/device_class.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeLayout extends StatelessWidget { 4 | final Widget mobile, tablet, desktop; 5 | 6 | final double tabletBreakpoint, desktopBreakpoint; 7 | 8 | final bool alwaysShowMobile; 9 | 10 | const NativeLayout({ 11 | @required this.mobile, 12 | this.tablet, 13 | this.desktop, 14 | this.tabletBreakpoint = 480.0, 15 | this.desktopBreakpoint = 1024.0, 16 | this.alwaysShowMobile = false, 17 | }); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | final double _width = MediaQuery.of(context).size.width; 22 | if (alwaysShowMobile == false) { 23 | if (_width == desktopBreakpoint) { 24 | return desktop ?? tablet ?? mobile; 25 | } 26 | if (_width == tabletBreakpoint) { 27 | return tablet ?? mobile; 28 | } 29 | } 30 | return mobile; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/native_widgets.dart: -------------------------------------------------------------------------------- 1 | library native_widgets; 2 | 3 | import 'dart:io'; 4 | 5 | import 'package:flutter/cupertino.dart'; 6 | import 'package:flutter/material.dart'; 7 | import 'package:flutter/rendering.dart'; 8 | import 'package:flutter/scheduler.dart'; 9 | import 'package:flutter/services.dart'; 10 | import 'package:flutter/widgets.dart'; 11 | import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; 12 | 13 | import 'app_bar/cupertino/search.dart'; 14 | import 'common/common_tiles/avatar_title.dart'; 15 | import 'common/common_tiles/base_tile.dart'; 16 | import 'common/common_tiles/basic_tile.dart'; 17 | import 'common/common_tiles/phone_tile.dart'; 18 | import 'common/search/cupertino_search_bar.dart'; 19 | import 'common/search/material_search_bar.dart'; 20 | import 'scaffold/ios_controllers/table_view_controller/controller.dart'; 21 | import 'scaffold/ios_controllers/master_detail_controller/controller.dart'; 22 | 23 | export 'package:flutter/cupertino.dart'; 24 | export 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; 25 | 26 | part 'app/main_app.dart'; 27 | part 'app_bar/app_bar.dart'; 28 | part 'app_bar/search_bar.dart'; 29 | part 'button/icon_button.dart'; 30 | part 'button/raised_button.dart'; 31 | part 'button/text_button.dart'; 32 | part 'common/list_tile.dart'; 33 | part 'common/routing.dart'; 34 | part 'common/search/native_search.dart'; 35 | part 'common/text.dart'; 36 | part 'dialog/alert_dialog.dart'; 37 | part 'icon/icon.dart'; 38 | part 'input/date_picker.dart'; 39 | part 'input/group_select.dart'; 40 | part 'input/text_field.dart'; 41 | part 'picker/picker.dart'; 42 | part 'picker/selection.dart'; 43 | part 'scaffold/list_view_scaffold.dart'; 44 | part 'scaffold/scaffold.dart'; 45 | part 'scaffold/search_scaffold.dart'; 46 | part 'status/circle_indicator.dart'; 47 | part 'switch/switch.dart'; 48 | part 'tabs/bottom_navigation.dart'; 49 | part 'tabs/top_navigation.dart'; 50 | part 'toolbar/bottom_toolbar.dart'; 51 | part 'utils/platform_switch.dart'; 52 | part 'layout/device_class.dart'; 53 | part 'scaffold/master_detail_scaffold.dart'; 54 | part 'common/widget.dart'; 55 | part 'scaffold/tab_scaffold.dart'; 56 | -------------------------------------------------------------------------------- /lib/picker/picker.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativePicker extends StatelessWidget { 4 | final bool showMaterial; 5 | final String selection; 6 | final Widget label, noItemsLabel, leading, trailing; 7 | final List items; 8 | final ValueChanged onSelected; 9 | 10 | NativePicker({ 11 | @required this.selection, 12 | @required this.items, 13 | this.showMaterial = false, 14 | this.onSelected, 15 | this.label, 16 | this.noItemsLabel, 17 | this.leading, 18 | this.trailing, 19 | }); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | if (Platform.isIOS && !showMaterial) { 24 | return ListTile( 25 | leading: const Icon(Icons.label), 26 | title: label ?? const Text('Select an Item'), 27 | subtitle: Text(selection), 28 | trailing: items != null && items.length == 1 29 | ? NativeLoadingIndicator() 30 | : null, 31 | onTap: () async { 32 | await showModalBottomSheet( 33 | context: context, 34 | builder: (BuildContext context) { 35 | return NativeSelection( 36 | value: selection, 37 | items: items, 38 | onChanged: onSelected, 39 | noItemsLabel: noItemsLabel ?? const Text("No Items Found"), 40 | ); 41 | }, 42 | ); 43 | }, 44 | ); 45 | } 46 | return ListTile( 47 | leading: leading, 48 | title: label ?? const Text('Select an Item'), 49 | subtitle: NativeSelection( 50 | showMaterial: showMaterial, 51 | value: selection, 52 | items: items, 53 | onChanged: onSelected, 54 | noItemsLabel: noItemsLabel ?? const Text("No Items Found"), 55 | ), 56 | trailing: trailing, 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/picker/selection.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeSelection extends StatelessWidget { 4 | final bool showMaterial; 5 | final String value; 6 | final Widget noItemsLabel; 7 | final List items; 8 | final ValueChanged onChanged; 9 | 10 | NativeSelection({ 11 | this.showMaterial = false, 12 | @required this.value, 13 | @required this.items, 14 | this.onChanged, 15 | this.noItemsLabel, 16 | }); 17 | 18 | double _kPickerSheetHeight = 216.0; 19 | 20 | double _kPickerItemHeight = 32.0; 21 | // double textScaleFactor = 1.0; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | if (items == null || items.isEmpty) { 26 | return Container( 27 | child: noItemsLabel ?? const Text("No Items"), 28 | ); 29 | } 30 | int _initialIndex = 0; 31 | int _index = 0; 32 | for (var _item in items) { 33 | if (_item == value) _initialIndex = _index; 34 | _index++; 35 | } 36 | 37 | final FixedExtentScrollController scrollController = 38 | new FixedExtentScrollController(initialItem: _initialIndex); 39 | if (Platform.isIOS && !showMaterial) { 40 | return new Container( 41 | height: _kPickerSheetHeight, 42 | color: Colors.transparent, 43 | child: new DefaultTextStyle( 44 | style: const TextStyle( 45 | color: CupertinoColors.black, 46 | fontSize: 22.0, 47 | ), 48 | child: new GestureDetector( 49 | // Blocks taps from propagating to the modal sheet and popping. 50 | onTap: () {}, 51 | child: new SafeArea( 52 | child: new CupertinoPicker( 53 | scrollController: scrollController, 54 | itemExtent: _kPickerItemHeight, 55 | backgroundColor: CupertinoColors.white, 56 | onSelectedItemChanged: (int index) => onChanged(items[index]), 57 | children: new List.generate(items.length, (int index) { 58 | return new Center( 59 | child: new Text( 60 | items[index], 61 | // textScaleFactor: textScaleFactor, 62 | style: const TextStyle(color: Colors.black), 63 | )); 64 | }), 65 | ), 66 | ), 67 | ), 68 | ), 69 | ); 70 | } 71 | 72 | return DropdownButton( 73 | value: value, 74 | items: items 75 | .map( 76 | (String item) => DropdownMenuItem( 77 | value: item, 78 | child: SizedBox( 79 | // width: 200.0, 80 | child: Text( 81 | item, 82 | // textScaleFactor: textScaleFactor, 83 | ))), 84 | ) 85 | .toList(), 86 | onChanged: (s) => onChanged(s)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/scaffold/ios_controllers/master_detail_controller/controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:native_widgets/native_widgets.dart'; 4 | 5 | typedef ItemWidgetBuilder = Widget Function( 6 | BuildContext context, dynamic item, bool tablet); 7 | typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index); 8 | 9 | class CupertinoMasterDetailController extends StatelessWidget { 10 | final ItemWidgetBuilder detailBuilder; 11 | final IndexedWidgetBuilder itemBuilder; 12 | final Widget onNull, onEmpty, appBar; 13 | final dynamic selectedItem; 14 | final ValueChanged itemSelected; 15 | final List items; 16 | 17 | CupertinoMasterDetailController({ 18 | @required this.detailBuilder, 19 | @required this.selectedItem, 20 | @required this.itemSelected, 21 | @required this.itemBuilder, 22 | @required this.items, 23 | this.appBar, 24 | this.onNull, 25 | this.onEmpty, 26 | }); 27 | 28 | Widget _buildMobileLayout(BuildContext context) { 29 | return Scaffold( 30 | body: CupertinoPageScaffold( 31 | child: CustomScrollView( 32 | semanticChildCount: items?.length ?? 0, 33 | slivers: [ 34 | CupertinoSliverNavigationBar( 35 | // trailing: trailingButtons, 36 | // middle: Text("Presidents"), 37 | largeTitle: Text("Presidents"), 38 | ), 39 | _ItemListing( 40 | onEmpty: onEmpty, 41 | onNull: onNull, 42 | itemBuilder: itemBuilder, 43 | items: items, 44 | selectedItem: selectedItem, 45 | itemSelectedCallback: (item) { 46 | Navigator.push( 47 | context, 48 | MaterialPageRoute( 49 | builder: (context) => detailBuilder(context, item, false)), 50 | ); 51 | }, 52 | ), 53 | ]))); 54 | 55 | // return Scaffold( 56 | // appBar: appBar, 57 | // body: _ItemListing( 58 | // onEmpty: onEmpty, 59 | // onNull: onNull, 60 | // itemBuilder: itemBuilder, 61 | // items: items, 62 | // selectedItem: selectedItem, 63 | // itemSelectedCallback: (item) { 64 | // Navigator.push( 65 | // context, 66 | // MaterialPageRoute( 67 | // builder: (context) => detailBuilder(context, item, false)), 68 | // ); 69 | // }, 70 | // ), 71 | // ); 72 | } 73 | 74 | Widget _buildTabletLayout(BuildContext context) { 75 | return OrientationBuilder(builder: (context, orientation) { 76 | return Row( 77 | children: [ 78 | Flexible( 79 | flex: orientation == Orientation.landscape ? 1 : 2, 80 | child: Scaffold( 81 | appBar: appBar, 82 | body: _ItemListing( 83 | onEmpty: onEmpty, 84 | onNull: onNull, 85 | itemBuilder: itemBuilder, 86 | items: items, 87 | selectedItem: selectedItem, 88 | itemSelectedCallback: itemSelected, 89 | ), 90 | ), 91 | ), 92 | Container( 93 | width: 1.0, 94 | color: Colors.grey[300], 95 | ), 96 | Flexible( 97 | flex: 3, 98 | child: detailBuilder(context, selectedItem, true), 99 | ), 100 | ], 101 | ); 102 | }); 103 | } 104 | 105 | @override 106 | Widget build(BuildContext context) { 107 | var shortestSide = MediaQuery.of(context).size.shortestSide; 108 | final bool useMobileLayout = shortestSide < 600; 109 | 110 | if (useMobileLayout) { 111 | return _buildMobileLayout(context); 112 | } 113 | 114 | return _buildTabletLayout(context); 115 | } 116 | } 117 | 118 | class _ItemListing extends StatelessWidget { 119 | _ItemListing({ 120 | @required this.itemSelectedCallback, 121 | this.selectedItem, 122 | this.itemBuilder, 123 | this.items, 124 | this.onNull, 125 | this.onEmpty, 126 | }); 127 | 128 | final ValueChanged itemSelectedCallback; 129 | final dynamic selectedItem; 130 | final IndexedWidgetBuilder itemBuilder; 131 | final List items; 132 | final Widget onNull, onEmpty; 133 | 134 | @override 135 | Widget build(BuildContext context) { 136 | if (items == null) { 137 | return onNull ?? Center(child: CircularProgressIndicator()); 138 | } 139 | 140 | if (items.isEmpty) { 141 | return onEmpty ?? Center(child: Text("No Items Found")); 142 | } 143 | 144 | return SliverList( 145 | delegate: SliverChildBuilderDelegate( 146 | (BuildContext context, int index) { 147 | final _child = itemBuilder(context, index); 148 | return GestureDetector( 149 | onTap: () => itemSelectedCallback(items[index]), 150 | child: _child, 151 | ); 152 | }, 153 | childCount: items.length, 154 | ), 155 | ); 156 | 157 | // return ListView.builder( 158 | // itemCount: items.length, 159 | // itemBuilder: (BuildContext context, int index) { 160 | // final _child = itemBuilder(context, index); 161 | // return GestureDetector( 162 | // onTap: () => itemSelectedCallback(items[index]), 163 | // child: _child, 164 | // ); 165 | // }, 166 | // ); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /lib/scaffold/ios_controllers/navigation_controller.dart: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /lib/scaffold/ios_controllers/table_view_controller/cell.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_slidable/flutter_slidable.dart'; 3 | 4 | import '../../../native_widgets.dart'; 5 | 6 | class CupertinoTableCell extends StatelessWidget { 7 | final bool selected; 8 | final bool editing; 9 | final bool canEdit; 10 | final bool canDelete; 11 | final bool lastItem; 12 | final Widget child; 13 | final String id; 14 | final VoidCallback onDelete, onTap; 15 | final SlidableController slideableController; 16 | final List leadingActions, trailingActions; 17 | final ValueChanged onSelected; 18 | 19 | // -- Styling -- 20 | final CupertinoAccessory accessory; 21 | final VoidCallback accessoryTap; 22 | final CupertinoEditingAction editingAction; 23 | final CupertinoEditingAccessory editingAccessory; 24 | final VoidCallback editingAccessoryTap; 25 | 26 | const CupertinoTableCell({ 27 | Key key, 28 | this.selected = false, 29 | this.canEdit = true, 30 | this.canDelete = true, 31 | this.editing = false, 32 | this.lastItem = false, 33 | this.trailingActions, 34 | this.leadingActions, 35 | this.onTap, 36 | this.child, 37 | @required this.id, 38 | this.onDelete, 39 | this.onSelected, 40 | this.accessory = CupertinoAccessory.disclosureIndicator, 41 | this.accessoryTap, 42 | this.editingAccessoryTap, 43 | this.editingAccessory = CupertinoEditingAccessory.none, 44 | this.editingAction = CupertinoEditingAction.select, 45 | this.slideableController, 46 | }) : super(key: key); 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | Widget _child; 51 | // NativeListTile _item = cell?.data as NativeListTile; 52 | 53 | final CupertinoListTileData _ios = CupertinoListTileData( 54 | hideLeadingIcon: true, 55 | style: CupertinoCellStyle.custom, 56 | accessory: accessory, 57 | editingAction: editingAction, 58 | editingAccessory: editingAccessory, 59 | padding: null, 60 | editingAccessoryTap: editingAccessoryTap, 61 | accessoryTap: accessoryTap, 62 | editingActionTap: () { 63 | switch (editingAction) { 64 | case CupertinoEditingAction.remove: 65 | onDelete(); 66 | break; 67 | case CupertinoEditingAction.select: 68 | onSelected(!selected); 69 | break; 70 | default: 71 | } 72 | }, 73 | ); 74 | 75 | switch (editingAction) { 76 | case CupertinoEditingAction.select: 77 | _child = GestureDetector( 78 | onTapDown: (TapDownDetails details) { 79 | if (!editing) { 80 | print("On Tap Down.."); 81 | onSelected(true); 82 | } 83 | }, 84 | onTapCancel: () { 85 | if (!editing) { 86 | print("On Tap Cancel.."); 87 | onSelected(false); 88 | } 89 | }, 90 | child: NativeListTile( 91 | editing: editing, 92 | selected: selected, 93 | child: child, 94 | ios: _ios, 95 | lastItem: lastItem, 96 | onTap: () { 97 | if (!editing) { 98 | onSelected(false); 99 | onTap(); 100 | } else { 101 | print("On Tap Down.."); 102 | onSelected(!selected); 103 | } 104 | }, 105 | ), 106 | ); 107 | break; 108 | case CupertinoEditingAction.remove: 109 | _child = GestureDetector( 110 | onTapDown: (TapDownDetails details) { 111 | if (!editing) { 112 | onSelected(true); 113 | } 114 | }, 115 | onTapCancel: () { 116 | if (!editing) { 117 | onSelected(false); 118 | } 119 | }, 120 | child: NativeListTile( 121 | editing: editing, 122 | selected: selected, 123 | child: child, 124 | ios: _ios, 125 | lastItem: lastItem, 126 | onTap: () { 127 | if (!editing) { 128 | print("Item Tapped..."); 129 | onSelected(false); 130 | onTap(); 131 | } 132 | }, 133 | ), 134 | ); 135 | break; 136 | default: 137 | _child = NativeListTile( 138 | editing: editing, 139 | selected: selected, 140 | child: child, 141 | ios: _ios, 142 | lastItem: lastItem, 143 | onTap: () { 144 | if (!editing) { 145 | print("Item Tapped..."); 146 | onSelected(false); 147 | onTap(); 148 | } 149 | }, 150 | ); 151 | } 152 | 153 | final List _trailingActions = []; 154 | 155 | if (trailingActions != null) { 156 | _trailingActions..addAll(trailingActions); 157 | } 158 | 159 | _trailingActions.add( 160 | new IconSlideAction( 161 | caption: 'Delete', 162 | color: Colors.red, 163 | icon: Icons.delete, 164 | onTap: onDelete, 165 | ), 166 | ); 167 | 168 | return Slidable( 169 | key: key, 170 | controller: slideableController, 171 | dismissal: SlidableDismissal( 172 | child: SlidableDrawerDismissal(), 173 | onDismissed: (actionType) { 174 | onDelete(); 175 | }, 176 | ), 177 | actionPane: SlidableDrawerActionPane(), 178 | actionExtentRatio: 0.25, 179 | child: _child, 180 | actions: leadingActions, 181 | secondaryActions: _trailingActions, 182 | ); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /lib/scaffold/ios_controllers/table_view_controller/controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_sticky_header/flutter_sticky_header.dart'; 4 | 5 | import '../../../native_widgets.dart'; 6 | 7 | typedef RefreshCallback = Future Function(); 8 | 9 | class CupertinoTableViewController extends StatelessWidget { 10 | final String title, previousTitle; 11 | final Widget leading, trailing; 12 | final ValueChanged onEditing; 13 | final RefreshCallback onRefresh; 14 | final bool showEditingButtonLeft, showEditingButtonRight, hideAppBarOnSearch; 15 | final bool isEditing, isSearching; 16 | final List sections; 17 | final List widgets, toolbarButtons; 18 | 19 | const CupertinoTableViewController({ 20 | @required this.title, 21 | this.isEditing = false, 22 | this.isSearching = false, 23 | this.previousTitle = "Back", 24 | this.leading, 25 | this.trailing, 26 | this.hideAppBarOnSearch = false, 27 | this.onEditing, 28 | this.onRefresh, 29 | this.toolbarButtons, 30 | this.showEditingButtonLeft = true, 31 | this.showEditingButtonRight = false, 32 | @required this.sections, 33 | this.widgets, 34 | }) : assert(showEditingButtonLeft != showEditingButtonRight); 35 | 36 | @override 37 | Widget build(BuildContext context) { 38 | final _editingButton = Container( 39 | padding: EdgeInsets.only(top: 10.0), 40 | child: CupertinoTableViewEditingButton( 41 | isEditing: isEditing, 42 | onPressed: () => onEditing(!isEditing), 43 | ), 44 | ); 45 | 46 | final _searchNavBar = []; 47 | 48 | if (!isSearching && hideAppBarOnSearch) { 49 | _searchNavBar.addAll([ 50 | CupertinoSliverNavigationBar( 51 | // heroTag: title ?? "Title", 52 | // transitionBetweenRoutes: false, 53 | largeTitle: Text(title ?? "Title"), 54 | // We're specifying a back label here because the previous page 55 | // is a Material page. CupertinoPageRoutes could auto-populate 56 | // these back labels. 57 | previousPageTitle: previousTitle ?? "", 58 | leading: showEditingButtonLeft ? _editingButton : leading, 59 | trailing: showEditingButtonRight ? _editingButton : trailing, 60 | ), 61 | CupertinoSliverRefreshControl(onRefresh: onRefresh), 62 | ]); 63 | } 64 | 65 | final _widgets = []; 66 | 67 | if (widgets != null) { 68 | for (Widget _widget in widgets) { 69 | _widgets.add(SliverToBoxAdapter(child: _widget)); 70 | } 71 | } 72 | 73 | final _sections = []; 74 | 75 | if (sections != null) { 76 | int _index = 0; 77 | for (CupertinoTableViewSection _section in sections) { 78 | _sections.add(new SliverStickyHeader( 79 | header: _section?.header == null 80 | ? null 81 | : new Container( 82 | color: CupertinoColors.lightBackgroundGray, 83 | padding: const EdgeInsets.symmetric( 84 | horizontal: 16.0, vertical: 5.0), 85 | alignment: Alignment.centerLeft, 86 | child: _section.header, 87 | ), 88 | sliver: SliverSafeArea( 89 | top: false, 90 | bottom: sections?.length == _index + 1, 91 | sliver: SliverList( 92 | delegate: _section.childrenDelegate, 93 | ), 94 | ), 95 | )); 96 | _index++; 97 | } 98 | } 99 | 100 | return DefaultTextStyle( 101 | style: Theme.of(context).textTheme.title, 102 | child: Scaffold( 103 | body: CustomScrollView( 104 | primary: true, 105 | slivers: [] 106 | ..addAll(_searchNavBar) 107 | ..addAll(_widgets) 108 | ..addAll(_sections), 109 | ), 110 | persistentFooterButtons: toolbarButtons, 111 | ), 112 | ); 113 | } 114 | } 115 | 116 | class CupertinoTableViewEditingButton extends StatelessWidget { 117 | final bool isEditing; 118 | final VoidCallback onPressed; 119 | 120 | const CupertinoTableViewEditingButton({ 121 | this.isEditing, 122 | this.onPressed, 123 | }); 124 | 125 | @override 126 | Widget build(BuildContext context) { 127 | if (isEditing) { 128 | return GestureDetector( 129 | onTap: onPressed, 130 | child: const Text("Cancel", 131 | style: TextStyle( 132 | fontWeight: FontWeight.bold, 133 | color: CupertinoColors.activeBlue, 134 | )), 135 | ); 136 | } 137 | return GestureDetector( 138 | onTap: onPressed, 139 | child: const Text("Edit", 140 | style: TextStyle( 141 | color: CupertinoColors.activeBlue, 142 | )), 143 | ); 144 | } 145 | } 146 | 147 | // Todo; Seconts for Tableview 148 | class CupertinoTableViewSection { 149 | final Widget header; 150 | final SliverChildDelegate childrenDelegate; 151 | 152 | const CupertinoTableViewSection({ 153 | this.header, 154 | @required this.childrenDelegate, 155 | }); 156 | } 157 | -------------------------------------------------------------------------------- /lib/scaffold/list_view_scaffold.dart: -------------------------------------------------------------------------------- 1 | // Alphabetial Search on Side 2 | // Editing Mode with Reorder and Delete 3 | // Swipe to Delete Actions 4 | 5 | part of native_widgets; 6 | 7 | /// iOS Table View Controller Functionality 8 | class NativeListViewScaffold extends StatelessWidget { 9 | final String title, previousTitle; 10 | final Widget leading, trailing; 11 | final VoidCallback viewDetails, onEditingComplete, onEditingStarted; 12 | final Duration refreshDuration; 13 | final RefreshCallback onRefresh; 14 | final CupertinoListViewData ios; 15 | final bool showListTabs, hideAppBarOnSearch; 16 | final bool isEditing, isSearching; 17 | final ValueChanged onEditing; 18 | final List sections; 19 | final List widgets; 20 | 21 | NativeListViewScaffold({ 22 | // this.item, 23 | this.viewDetails, 24 | this.onEditingComplete, 25 | this.onEditingStarted, 26 | this.previousTitle, 27 | this.title, 28 | this.trailing, 29 | this.leading, 30 | this.onRefresh, 31 | this.ios, 32 | this.hideAppBarOnSearch = false, 33 | this.showListTabs = false, 34 | this.refreshDuration = const Duration(seconds: 3), 35 | this.isSearching = false, 36 | this.isEditing = false, 37 | this.onEditing, 38 | List children = const [], 39 | this.widgets, 40 | }) : sections = [NativeListViewSection(children: children)]; 41 | 42 | NativeListViewScaffold.builder({ 43 | // this.item, 44 | this.viewDetails, 45 | this.onEditingComplete, 46 | this.onEditingStarted, 47 | this.previousTitle, 48 | this.title, 49 | this.trailing, 50 | this.leading, 51 | this.onRefresh, 52 | this.hideAppBarOnSearch = false, 53 | this.ios, 54 | this.showListTabs = false, 55 | this.refreshDuration = const Duration(seconds: 3), 56 | this.isSearching = false, 57 | this.isEditing = false, 58 | this.onEditing, 59 | @required IndexedWidgetBuilder itemBuilder, 60 | int itemCount, 61 | this.widgets, 62 | }) : sections = [ 63 | NativeListViewSection.builder( 64 | itemBuilder: itemBuilder, 65 | itemCount: itemCount, 66 | ) 67 | ]; 68 | 69 | const NativeListViewScaffold.sectioned({ 70 | // this.item, 71 | this.viewDetails, 72 | this.onEditingComplete, 73 | this.onEditingStarted, 74 | this.previousTitle, 75 | this.title, 76 | this.trailing, 77 | this.hideAppBarOnSearch = false, 78 | this.leading, 79 | this.onRefresh, 80 | this.ios, 81 | this.showListTabs = false, 82 | this.refreshDuration = const Duration(seconds: 3), 83 | this.isSearching = false, 84 | this.isEditing = false, 85 | this.onEditing, 86 | @required this.sections, 87 | this.widgets, 88 | }); 89 | 90 | @override 91 | Widget build(BuildContext context) { 92 | return PlatformWidget( 93 | ios: (BuildContext context) { 94 | return CupertinoTableViewController( 95 | leading: leading, 96 | trailing: trailing, 97 | title: title, 98 | onRefresh: onRefresh, 99 | hideAppBarOnSearch: hideAppBarOnSearch, 100 | previousTitle: previousTitle, 101 | onEditing: onEditing, 102 | isEditing: isEditing, 103 | isSearching: isSearching, 104 | widgets: widgets, 105 | showEditingButtonLeft: ios?.showEditingButtonLeft, 106 | showEditingButtonRight: ios?.showEditingButtonRight, 107 | sections: sections 108 | .map( 109 | (NativeListViewSection item) => new CupertinoTableViewSection( 110 | header: item?.header == null ? null : item.header, 111 | childrenDelegate: item.childrenDelegate, 112 | )) 113 | .toList(), 114 | ); 115 | }, 116 | android: (BuildContext context) { 117 | return Container(); 118 | }, 119 | ); 120 | } 121 | } 122 | 123 | typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index); 124 | 125 | class NativeListViewSection { 126 | final Widget header; 127 | final SliverChildDelegate childrenDelegate; 128 | 129 | NativeListViewSection({ 130 | this.header, 131 | @required List children, 132 | bool addAutomaticKeepAlives = true, 133 | bool addRepaintBoundaries = true, 134 | bool addSemanticIndexes = true, 135 | }) : childrenDelegate = SliverChildListDelegate( 136 | children, 137 | addAutomaticKeepAlives: addAutomaticKeepAlives, 138 | addRepaintBoundaries: addRepaintBoundaries, 139 | addSemanticIndexes: addSemanticIndexes, 140 | ); 141 | 142 | NativeListViewSection.builder({ 143 | this.header, 144 | @required IndexedWidgetBuilder itemBuilder, 145 | int itemCount, 146 | bool addAutomaticKeepAlives = true, 147 | bool addRepaintBoundaries = true, 148 | bool addSemanticIndexes = true, 149 | }) : childrenDelegate = SliverChildBuilderDelegate( 150 | itemBuilder, 151 | childCount: itemCount, 152 | addAutomaticKeepAlives: addAutomaticKeepAlives, 153 | addRepaintBoundaries: addRepaintBoundaries, 154 | addSemanticIndexes: addSemanticIndexes, 155 | ); 156 | } 157 | 158 | typedef RefreshCallback = Future> Function(); 159 | 160 | class CupertinoListViewData { 161 | final bool showEditingButtonLeft, showEditingButtonRight; 162 | 163 | const CupertinoListViewData({ 164 | this.showEditingButtonLeft = false, 165 | this.showEditingButtonRight = false, 166 | }); 167 | } 168 | -------------------------------------------------------------------------------- /lib/scaffold/master_detail_scaffold.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeMasterDetailScaffold extends StatelessWidget { 4 | final ItemWidgetBuilder detailBuilder; 5 | final IndexedWidgetBuilder itemBuilder; 6 | final Widget onNull, onEmpty, appBar; 7 | final dynamic selectedItem; 8 | final ValueChanged itemSelected; 9 | final List items; 10 | 11 | NativeMasterDetailScaffold({ 12 | @required this.detailBuilder, 13 | @required this.selectedItem, 14 | @required this.itemSelected, 15 | @required this.itemBuilder, 16 | this.onNull, 17 | this.onEmpty, 18 | this.items, 19 | this.appBar, 20 | }); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return CupertinoMasterDetailController( 25 | detailBuilder: detailBuilder, 26 | selectedItem: selectedItem, 27 | itemBuilder: itemBuilder, 28 | items: items, 29 | itemSelected: itemSelected, 30 | appBar: appBar, 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/scaffold/search_scaffold.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // class NativeSearchScaffold extends StatefulWidget { 4 | // final Widget child, title; 5 | 6 | // NativeSearchScaffold({ 7 | // @required this.title, 8 | // this.child, 9 | // }); 10 | 11 | // @override 12 | // _NativeSearchScaffoldState createState() => _NativeSearchScaffoldState(); 13 | // } 14 | 15 | // class _NativeSearchScaffoldState extends State 16 | // with SingleTickerProviderStateMixin { 17 | // TextStyle searchText; 18 | // Color searchBackground, searchIconColor, searchCursorColor; 19 | 20 | // TextEditingController _searchTextController; 21 | // FocusNode _searchFocusNode = new FocusNode(); 22 | // Animation _animation; 23 | // AnimationController _animationController; 24 | 25 | // @override 26 | // void initState() { 27 | // _searchTextController = TextEditingController(); 28 | 29 | // _animationController = new AnimationController( 30 | // duration: new Duration(milliseconds: 200), 31 | // vsync: this, 32 | // ); 33 | // _animation = new CurvedAnimation( 34 | // parent: _animationController, 35 | // curve: Curves.easeInOut, 36 | // reverseCurve: Curves.easeInOut, 37 | // ); 38 | // _searchFocusNode.addListener(() { 39 | // if (!_animationController.isAnimating) { 40 | // _animationController.forward(); 41 | // } 42 | // }); 43 | // _startSearch(); 44 | // super.initState(); 45 | // } 46 | 47 | // void _startSearch() { 48 | // _searchTextController.clear(); 49 | // _animationController.forward(); 50 | // } 51 | 52 | // void _cancelSearch() { 53 | // // if (widget.alwaysShowAppBar) { 54 | // _searchTextController.clear(); 55 | // _searchFocusNode.unfocus(); 56 | // _animationController.reverse(); 57 | // // } 58 | // // widget.onSearchPressed(); 59 | // } 60 | 61 | // void _clearSearch() { 62 | // _searchTextController.clear(); 63 | // } 64 | 65 | // @override 66 | // Widget build(BuildContext context) { 67 | // if (Platform.isIOS) { 68 | // return CupertinoPageScaffold( 69 | // child: CustomScrollView( 70 | // semanticChildCount: 2, 71 | // slivers: [ 72 | // CupertinoSliverNavigationBar( 73 | // largeTitle: widget.title, 74 | // trailing: Icon(CupertinoIcons.info), 75 | // leading: Icon(CupertinoIcons.music_note), 76 | // ), 77 | // SliverFillRemaining( 78 | // child: Column( 79 | // children: [ 80 | // new IOSSearchBar( 81 | // controller: _searchTextController, 82 | // focusNode: _searchFocusNode, 83 | // animation: _animation, 84 | // onCancel: _cancelSearch, 85 | // onClear: _clearSearch, 86 | // // onUpdate: widget?.onChanged, 87 | // ), 88 | // widget?.child ?? Container(), 89 | // ], 90 | // )), 91 | // ], 92 | // ), 93 | // ); 94 | // } 95 | // return Scaffold( 96 | // appBar: AppBar( 97 | // title: widget.title, 98 | // ), 99 | // body: widget?.child ?? Container(), 100 | // ); 101 | // } 102 | // } 103 | -------------------------------------------------------------------------------- /lib/scaffold/tab_scaffold.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeTabScaffold extends StatelessWidget { 4 | final List tabs; 5 | final List pages; 6 | 7 | NativeTabScaffold({ 8 | Key key, 9 | @required this.tabs, 10 | this.pages, 11 | }) : assert(tabs.length == pages?.length ?? 0), 12 | super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return PlatformWidget( 17 | key: key, 18 | ios: (BuildContext context) { 19 | return CupertinoTabScaffold( 20 | tabBar: CupertinoTabBar(items: tabs), 21 | tabBuilder: (BuildContext context, int index) { 22 | return CupertinoTabView( 23 | builder: (BuildContext context) { 24 | return pages[index]?.child; 25 | }, 26 | defaultTitle: pages[index]?.title, 27 | ); 28 | ; 29 | }, 30 | ); 31 | }, 32 | android: (BuildContext context) { 33 | return _BottomTabs( 34 | tabs: tabs, 35 | pages: pages, 36 | ); 37 | }, 38 | ); 39 | } 40 | } 41 | 42 | class NativeTabView extends StatelessWidget { 43 | final Widget child; 44 | final String title; 45 | 46 | NativeTabView({ 47 | Key key, 48 | @required this.child, 49 | @required this.title, 50 | }) : super(key: key); 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return PlatformWidget( 55 | key: key, 56 | ios: (BuildContext context) { 57 | return CupertinoTabView( 58 | builder: (BuildContext context) { 59 | return child; 60 | }, 61 | defaultTitle: title, 62 | ); 63 | }, 64 | android: (BuildContext context) { 65 | return Scaffold( 66 | appBar: AppBar( 67 | title: Text(title), 68 | ), 69 | body: child, 70 | ); 71 | }, 72 | ); 73 | } 74 | } 75 | 76 | class _BottomTabs extends StatefulWidget { 77 | final List tabs; 78 | final List pages; 79 | 80 | _BottomTabs({ 81 | Key key, 82 | @required this.tabs, 83 | this.pages, 84 | }) : super(key: key); 85 | 86 | @override 87 | _BottomTabsState createState() { 88 | return new _BottomTabsState(); 89 | } 90 | } 91 | 92 | class _BottomTabsState extends State<_BottomTabs> { 93 | int _currentIndex = 0; 94 | bool _isDisposed = false; 95 | 96 | @override 97 | void dispose() { 98 | _isDisposed = true; 99 | super.dispose(); 100 | } 101 | 102 | @override 103 | Widget build(BuildContext context) { 104 | return DefaultTabController( 105 | length: widget?.pages?.length ?? 0, 106 | child: Scaffold( 107 | body: widget?.pages[_currentIndex]?.child ?? Container(), 108 | bottomNavigationBar: BottomNavigationBar( 109 | onTap: (int index) { 110 | if (!_isDisposed) 111 | setState(() { 112 | _currentIndex = index; 113 | }); 114 | }, 115 | currentIndex: _currentIndex, 116 | items: widget.tabs, 117 | ), 118 | )); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/status/circle_indicator.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // Native Loading Indicator 4 | class NativeLoadingIndicator extends StatelessWidget { 5 | final Widget text; 6 | final bool center; 7 | final bool showMaterial; 8 | 9 | NativeLoadingIndicator({ 10 | Key key, 11 | this.text, 12 | this.center, 13 | this.showMaterial = false, 14 | }); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | final bool _isIos = showCupertino(showMaterial: showMaterial); 19 | 20 | if (_isIos) { 21 | return text == null 22 | ? center != null && center 23 | ? Center( 24 | child: CupertinoActivityIndicator( 25 | key: key, 26 | animating: true, 27 | ), 28 | ) 29 | : CupertinoActivityIndicator( 30 | key: key, 31 | animating: true, 32 | ) 33 | : Center( 34 | child: Column( 35 | mainAxisSize: MainAxisSize.min, 36 | crossAxisAlignment: CrossAxisAlignment.center, 37 | mainAxisAlignment: MainAxisAlignment.center, 38 | children: [ 39 | CupertinoActivityIndicator( 40 | key: key, 41 | animating: true, 42 | ), 43 | Container( 44 | height: 10.0, 45 | ), 46 | text, 47 | ], 48 | ), 49 | ); 50 | } 51 | return text == null 52 | ? center != null && center 53 | ? Center( 54 | child: CircularProgressIndicator(key: key), 55 | ) 56 | : CircularProgressIndicator(key: key) 57 | : Center( 58 | child: Column( 59 | mainAxisSize: MainAxisSize.min, 60 | crossAxisAlignment: CrossAxisAlignment.center, 61 | mainAxisAlignment: MainAxisAlignment.center, 62 | children: [ 63 | CircularProgressIndicator( 64 | key: key, 65 | ), 66 | Container( 67 | height: 10.0, 68 | ), 69 | text, 70 | ], 71 | ), 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/switch/switch.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // Native Switch 4 | class NativeSwitch extends StatelessWidget { 5 | final bool value; 6 | final ValueChanged onChanged; 7 | final Color activeColor; 8 | 9 | NativeSwitch({ 10 | Key key, 11 | @required this.value, 12 | @required this.onChanged, 13 | this.activeColor, 14 | }); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return PlatformWidget( 19 | key: key, 20 | ios: (BuildContext context) => CupertinoSwitch( 21 | key: key, 22 | value: value, 23 | onChanged: onChanged, 24 | activeColor: 25 | activeColor == null ? CupertinoColors.activeGreen : activeColor, 26 | ), 27 | android: (BuildContext context) => Switch( 28 | key: key, 29 | value: value, 30 | onChanged: onChanged, 31 | activeColor: activeColor, 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/tabs/bottom_navigation.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // Native Tab Bar 4 | class NativeBottomTabBar extends StatelessWidget { 5 | final List items; 6 | final ValueChanged onTap; 7 | final Color activeColor; 8 | final double iconSize; 9 | final int currentIndex; 10 | final bool showMaterial; 11 | 12 | NativeBottomTabBar({ 13 | Key key, 14 | @required this.items, 15 | this.onTap, 16 | @required this.activeColor, 17 | this.currentIndex, 18 | this.iconSize, 19 | this.showMaterial = false, 20 | }); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | final bool _isIos = showCupertino(showMaterial: showMaterial); 25 | 26 | if (_isIos) { 27 | return CupertinoTabBar( 28 | key: key, 29 | items: items, 30 | onTap: onTap, 31 | currentIndex: currentIndex == null ? 0 : currentIndex, 32 | activeColor: 33 | activeColor == null ? CupertinoColors.activeBlue : activeColor, 34 | backgroundColor: Colors.transparent, 35 | iconSize: iconSize == null ? 30.0 : iconSize, 36 | ); 37 | } 38 | return BottomNavigationBar( 39 | key: key, 40 | type: BottomNavigationBarType.fixed, 41 | onTap: onTap, 42 | currentIndex: currentIndex == null ? 0 : currentIndex, 43 | fixedColor: activeColor, 44 | items: items, 45 | iconSize: iconSize == null ? 30.0 : iconSize, 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/tabs/top_navigation.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | class NativeTopTabs extends StatelessWidget { 4 | final bool showMaterial; 5 | final Color selectedColor, borderColor, pressedColor; 6 | final ValueChanged onValueChanged; 7 | final dynamic groupValue; 8 | final List tabs; 9 | 10 | NativeTopTabs({ 11 | this.showMaterial = false, 12 | this.selectedColor, 13 | this.borderColor, 14 | this.pressedColor, 15 | this.onValueChanged, 16 | this.tabs, 17 | this.groupValue, 18 | }); 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | final bool _isIos = showCupertino(showMaterial: showMaterial); 23 | final Map iosTabs = const {}; 24 | 25 | int _index = 0; 26 | for (Widget item in tabs) { 27 | iosTabs[_index] = item; 28 | } 29 | _index++; 30 | 31 | if (_isIos) { 32 | return CupertinoSegmentedControl( 33 | selectedColor: selectedColor, 34 | borderColor: borderColor, 35 | onValueChanged: onValueChanged, 36 | pressedColor: pressedColor, 37 | children: iosTabs, 38 | groupValue: groupValue, 39 | ); 40 | } 41 | 42 | return TabBar( 43 | tabs: tabs, 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/toolbar/bottom_toolbar.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | // class NativeToolbar extends StatelessWidget { 4 | // final List buttons; 5 | 6 | // NativeToolbar({this.buttons}); 7 | 8 | // @override 9 | // Widget build(BuildContext context) { 10 | // return new Container( 11 | // // height: 48.0, 12 | // child: BottomAppBar( 13 | // shape: const CircularNotchedRectangle(), 14 | // child: 15 | // buttons == null ? Container(height: 25.0) : Row(children: buttons), 16 | // ), 17 | // ); 18 | // } 19 | // } 20 | 21 | class NativeToolBar extends StatelessWidget { 22 | final Widget leading, trailing, middle; 23 | final double height; 24 | 25 | NativeToolBar({ 26 | this.leading, 27 | this.trailing, 28 | this.middle, 29 | this.height = 25.0, 30 | }); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return Container( 35 | height: height, 36 | width: MediaQuery.of(context).size.width - 20, 37 | child: Row( 38 | crossAxisAlignment: CrossAxisAlignment.center, 39 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 40 | children: [ 41 | leading ?? Container(), 42 | middle ?? Container(), 43 | trailing ?? Container(), 44 | ], 45 | ), 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/utils/platform_switch.dart: -------------------------------------------------------------------------------- 1 | part of native_widgets; 2 | 3 | bool showCupertino({bool showMaterial = false}) { 4 | if (showMaterial != null && showMaterial) return false; 5 | if (Platform.isIOS) return true; 6 | if (Platform.isMacOS) return true; 7 | return false; 8 | } 9 | -------------------------------------------------------------------------------- /native_widgets.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.8.1" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.0" 25 | charcode: 26 | dependency: transitive 27 | description: 28 | name: charcode 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.3.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.1.0" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.15.0" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "2.1.1" 53 | crypto: 54 | dependency: transitive 55 | description: 56 | name: crypto 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.1.5" 60 | cupertino_icons: 61 | dependency: transitive 62 | description: 63 | name: cupertino_icons 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "0.1.3" 67 | fake_async: 68 | dependency: transitive 69 | description: 70 | name: fake_async 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.2.0" 74 | flutter: 75 | dependency: "direct main" 76 | description: flutter 77 | source: sdk 78 | version: "0.0.0" 79 | flutter_list_drag_and_drop: 80 | dependency: "direct main" 81 | description: 82 | name: flutter_list_drag_and_drop 83 | url: "https://pub.dartlang.org" 84 | source: hosted 85 | version: "0.1.6" 86 | flutter_localizations: 87 | dependency: "direct main" 88 | description: flutter 89 | source: sdk 90 | version: "0.0.0" 91 | flutter_platform_widgets: 92 | dependency: "direct main" 93 | description: 94 | name: flutter_platform_widgets 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.32.5" 98 | flutter_slidable: 99 | dependency: "direct main" 100 | description: 101 | name: flutter_slidable 102 | url: "https://pub.dartlang.org" 103 | source: hosted 104 | version: "0.5.7" 105 | flutter_sticky_header: 106 | dependency: "direct main" 107 | description: 108 | name: flutter_sticky_header 109 | url: "https://pub.dartlang.org" 110 | source: hosted 111 | version: "0.4.6" 112 | flutter_test: 113 | dependency: "direct dev" 114 | description: flutter 115 | source: sdk 116 | version: "0.0.0" 117 | intl: 118 | dependency: "direct main" 119 | description: 120 | name: intl 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "0.17.0" 124 | matcher: 125 | dependency: transitive 126 | description: 127 | name: matcher 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "0.12.10" 131 | meta: 132 | dependency: transitive 133 | description: 134 | name: meta 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.7.0" 138 | path: 139 | dependency: transitive 140 | description: 141 | name: path 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "1.8.0" 145 | sky_engine: 146 | dependency: transitive 147 | description: flutter 148 | source: sdk 149 | version: "0.0.99" 150 | source_span: 151 | dependency: transitive 152 | description: 153 | name: source_span 154 | url: "https://pub.dartlang.org" 155 | source: hosted 156 | version: "1.8.1" 157 | stack_trace: 158 | dependency: transitive 159 | description: 160 | name: stack_trace 161 | url: "https://pub.dartlang.org" 162 | source: hosted 163 | version: "1.10.0" 164 | stream_channel: 165 | dependency: transitive 166 | description: 167 | name: stream_channel 168 | url: "https://pub.dartlang.org" 169 | source: hosted 170 | version: "2.1.0" 171 | string_scanner: 172 | dependency: transitive 173 | description: 174 | name: string_scanner 175 | url: "https://pub.dartlang.org" 176 | source: hosted 177 | version: "1.1.0" 178 | term_glyph: 179 | dependency: transitive 180 | description: 181 | name: term_glyph 182 | url: "https://pub.dartlang.org" 183 | source: hosted 184 | version: "1.2.0" 185 | test_api: 186 | dependency: transitive 187 | description: 188 | name: test_api 189 | url: "https://pub.dartlang.org" 190 | source: hosted 191 | version: "0.4.2" 192 | typed_data: 193 | dependency: transitive 194 | description: 195 | name: typed_data 196 | url: "https://pub.dartlang.org" 197 | source: hosted 198 | version: "1.3.0" 199 | uuid: 200 | dependency: "direct main" 201 | description: 202 | name: uuid 203 | url: "https://pub.dartlang.org" 204 | source: hosted 205 | version: "2.2.2" 206 | value_layout_builder: 207 | dependency: transitive 208 | description: 209 | name: value_layout_builder 210 | url: "https://pub.dartlang.org" 211 | source: hosted 212 | version: "0.1.0" 213 | vector_math: 214 | dependency: transitive 215 | description: 216 | name: vector_math 217 | url: "https://pub.dartlang.org" 218 | source: hosted 219 | version: "2.1.0" 220 | sdks: 221 | dart: ">=2.12.0 <3.0.0" 222 | flutter: ">=1.17.0" 223 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: native_widgets 2 | description: A new Flutter package for using Android and iOS natively on each platform. 3 | version: 1.3.7+1 4 | author: Rhodes Davis Jr. 5 | homepage: https://github.com/fluttercommunity/native_widgets 6 | maintainer: Rody Davis (@rodydavis) 7 | 8 | environment: 9 | sdk: '>=2.10.0 <3.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | flutter_list_drag_and_drop: ^0.1.6 15 | flutter_localizations: 16 | sdk: flutter 17 | flutter_platform_widgets: ^0.32.4 18 | flutter_slidable: ^0.5.4 19 | flutter_sticky_header: ^0.4.0 20 | intl: ^0.17.0 21 | uuid: ^2.0.4 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | 27 | # dependency_overrides: 28 | # flutter_sticky_header: 29 | # git: https://github.com/rodydavis/flutter_sticky_header 30 | flutter: null 31 | -------------------------------------------------------------------------------- /test/native_widgets_test.dart: -------------------------------------------------------------------------------- 1 | // import 'package:native_widgets/native_widgets.dart'; 2 | // import 'package:test/test.dart'; 3 | 4 | // void main() { 5 | // test('Checks for Not Null', () { 6 | // final NativeButton button = new NativeButton(); 7 | // expect(button.child, !null); 8 | // }); 9 | // } 10 | --------------------------------------------------------------------------------