From 2d9d7dd23b7f92a590cfa831729e2d9bba837e27 Mon Sep 17 00:00:00 2001 From: rafaelrosadev Date: Mon, 23 Dec 2024 11:16:57 -0300 Subject: [PATCH] Atualizado dependencias do packege --- .gitignore | 26 + CHANGELOG.md | 326 +++++++ CONTRIBUTING.md | 40 + LICENSE | 25 + README.md | 327 +++++++ analysis_options.yaml | 4 + example/.gitignore | 46 + example/.metadata | 30 + example/README.md | 16 + example/android/.gitignore | 11 + example/android/app/build.gradle | 59 ++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 42 + .../com/example/example/MainActivity.kt | 6 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + example/android/build.gradle | 31 + example/android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 6 + example/android/settings.gradle | 11 + example/ios/.gitignore | 32 + example/ios/Flutter/AppFrameworkInfo.plist | 26 + example/ios/Flutter/Debug.xcconfig | 2 + example/ios/Flutter/Release.xcconfig | 2 + example/ios/Podfile | 41 + example/ios/Podfile.lock | 22 + example/ios/Runner.xcodeproj/project.pbxproj | 550 +++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 ++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + example/ios/Runner/Base.lproj/Main.storyboard | 26 + example/ios/Runner/Info.plist | 49 + example/ios/Runner/Runner-Bridging-Header.h | 1 + example/lib/main.dart | 383 ++++++++ example/linux/.gitignore | 1 + example/linux/CMakeLists.txt | 116 +++ example/linux/flutter/CMakeLists.txt | 91 ++ .../flutter/generated_plugin_registrant.cc | 11 + .../flutter/generated_plugin_registrant.h | 15 + example/linux/flutter/generated_plugins.cmake | 23 + example/linux/main.cc | 6 + example/linux/my_application.cc | 105 +++ example/linux/my_application.h | 18 + example/pubspec.yaml | 78 ++ example/web/favicon.png | Bin 0 -> 917 bytes example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes example/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes example/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes example/web/index.html | 58 ++ example/web/manifest.json | 35 + flutter_typeahead.gif | Bin 0 -> 354997 bytes flutter_typeahead.iml | 22 + lib/flutter_typeahead.dart | 17 + .../cupertino_text_field_configuration.dart | 185 ++++ .../field/cupertino_typeahead_field.dart | 560 +++++++++++ .../field/cupertino_typeahead_form_field.dart | 190 ++++ .../cupertino_suggestions_box.dart | 212 +++++ .../cupertino_suggestions_box_controller.dart | 33 + .../cupertino_suggestions_box_decoration.dart | 26 + .../cupertino_suggestions_list.dart | 376 ++++++++ ...eyboard_suggestion_selection_notifier.dart | 21 + .../field/text_field_configuration.dart | 274 ++++++ lib/src/material/field/typeahead_field.dart | 885 ++++++++++++++++++ .../material/field/typeahead_form_field.dart | 199 ++++ .../suggestions_box/suggestions_box.dart | 223 +++++ .../suggestions_box_controller.dart | 37 + .../suggestions_box_decoration.dart | 57 ++ .../suggestions_box/suggestions_list.dart | 411 ++++++++ ...fresh_suggestion_focus_index_notifier.dart | 13 + lib/src/typedef.dart | 11 + lib/src/utils.dart | 5 + pubspec.yaml | 51 + scripts/code_analysis.sh | 9 + scripts/publish.sh | 2 + scripts/run_tests.sh | 2 + test/flutter_typeahead_test.dart | 254 +++++ 112 files changed, 7189 insertions(+) create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 example/.gitignore create mode 100644 example/.metadata create mode 100644 example/README.md create mode 100644 example/android/.gitignore create mode 100644 example/android/app/build.gradle create mode 100644 example/android/app/src/debug/AndroidManifest.xml create mode 100644 example/android/app/src/main/AndroidManifest.xml create mode 100644 example/android/app/src/main/kotlin/com/example/example/MainActivity.kt create mode 100644 example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/values-night/styles.xml create mode 100644 example/android/app/src/main/res/values/styles.xml create mode 100644 example/android/app/src/profile/AndroidManifest.xml create mode 100644 example/android/build.gradle create mode 100644 example/android/gradle.properties create mode 100644 example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 example/android/settings.gradle create mode 100644 example/ios/.gitignore create mode 100644 example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 example/ios/Flutter/Debug.xcconfig create mode 100644 example/ios/Flutter/Release.xcconfig create mode 100644 example/ios/Podfile create mode 100644 example/ios/Podfile.lock create mode 100644 example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 example/ios/Runner/AppDelegate.swift create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 example/ios/Runner/Info.plist create mode 100644 example/ios/Runner/Runner-Bridging-Header.h create mode 100644 example/lib/main.dart create mode 100644 example/linux/.gitignore create mode 100644 example/linux/CMakeLists.txt create mode 100644 example/linux/flutter/CMakeLists.txt create mode 100644 example/linux/flutter/generated_plugin_registrant.cc create mode 100644 example/linux/flutter/generated_plugin_registrant.h create mode 100644 example/linux/flutter/generated_plugins.cmake create mode 100644 example/linux/main.cc create mode 100644 example/linux/my_application.cc create mode 100644 example/linux/my_application.h create mode 100644 example/pubspec.yaml create mode 100644 example/web/favicon.png create mode 100644 example/web/icons/Icon-192.png create mode 100644 example/web/icons/Icon-512.png create mode 100644 example/web/icons/Icon-maskable-192.png create mode 100644 example/web/icons/Icon-maskable-512.png create mode 100644 example/web/index.html create mode 100644 example/web/manifest.json create mode 100644 flutter_typeahead.gif create mode 100644 flutter_typeahead.iml create mode 100644 lib/flutter_typeahead.dart create mode 100644 lib/src/cupertino/field/cupertino_text_field_configuration.dart create mode 100644 lib/src/cupertino/field/cupertino_typeahead_field.dart create mode 100644 lib/src/cupertino/field/cupertino_typeahead_form_field.dart create mode 100644 lib/src/cupertino/suggestions_box/cupertino_suggestions_box.dart create mode 100644 lib/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart create mode 100644 lib/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart create mode 100644 lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart create mode 100644 lib/src/keyboard_suggestion_selection_notifier.dart create mode 100644 lib/src/material/field/text_field_configuration.dart create mode 100644 lib/src/material/field/typeahead_field.dart create mode 100644 lib/src/material/field/typeahead_form_field.dart create mode 100644 lib/src/material/suggestions_box/suggestions_box.dart create mode 100644 lib/src/material/suggestions_box/suggestions_box_controller.dart create mode 100644 lib/src/material/suggestions_box/suggestions_box_decoration.dart create mode 100644 lib/src/material/suggestions_box/suggestions_list.dart create mode 100644 lib/src/should_refresh_suggestion_focus_index_notifier.dart create mode 100644 lib/src/typedef.dart create mode 100644 lib/src/utils.dart create mode 100644 pubspec.yaml create mode 100644 scripts/code_analysis.sh create mode 100644 scripts/publish.sh create mode 100644 scripts/run_tests.sh create mode 100644 test/flutter_typeahead_test.dart diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f4cd55e --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ +.flutter-plugins +.flutter-plugins-dependencies + +build/ +example/.flutter-plugins* +ios/.generated/ +ios/Flutter/Generated.xcconfig +ios/Runner/GeneratedPluginRegistrant.* + +.idea +pubspec.lock +flutter_typeahead + +doc + +example/android/gradle/wrapper/gradle-wrapper.jar +example/android/gradlew +example/android/gradlew.bat +example/example.iml +example/ios/Flutter/flutter_export_environment.sh +example/pubspec.lock` \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..25c6278 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,326 @@ +## 4.3.7 - 26-February-2023 + +Update Changelog file + +## 4.3.6 - 18-February-2023 +Fixed visibility of cupertino decoration and formated code + +## 4.3.5 - 17-February-2023 +Fix in visibility of suggestions box classes + +## 4.3.4 - 16-February-2023 +Improved the main example to be able to read it in pub dev, + +## 4.3.3 - 1-Feburary-2023 + +-- Apply PR to fix onSelected issue introduced in Flutter 3.7.0 + +## 4.3.2 - 28-January-2023 + +-- Update sdk level to 2.19.0 for Flutter 3.7.0 + +## 4.3.1 - 28-January-2023 + +-- PR #447 - fix: Use maybeOf for scrollable to not throw an exception in flutter … + +## 4.3.0 - 15-November-2022 + +-- PR #436 - Added onReset callback to TypeAheadFormField +-- PR #435 - Block up and down keys + +## 4.2.0 - 27-October-2022 + +-- PR #432 - Fix suggestions box behavior on web +-- PR #431 - Add autoFlipListDirection option + +## 4.1.1 - 17-September-2022 + +-- PR #428 - Fix some issues with web / arrows etc. + +## 4.1.0 - 5-September-2022 + +-- PR #409 - Add null safety to suggestions box controller +-- PR #417 - Improved support for VoiceOver/TalkBack +-- PR #418 - Feat/key up down +-- PR #422 - Adding hideKeyboardOnDrag option +-- PR #424 - Updated README: added pub.dev shield + +## 4.0.0 - 15-May-2022 + +-- PR #395 - Fix Flutter 3.0 warnings + +## 3.2.7 - 15-May-2022 + +-- REVERT PR #395 - Fix Flutter 3.0 warnings + +## 3.2.6 - 15-May-2022 + +-- PR #393 - Hide suggestion on close issue fix +-- PR #395 - Fix Flutter 3.0 warnings + +## 3.2.5 - 18-Apr-2022 + +-- PR #383 - Fix maxLengthEnforced deprecation + +## 3.2.4 - 9-Dec-2021 + +-- PR #360 - Resize before opening box (fixes issue 220) + +## 3.2.3 - 21-Nov-2021 + +-- PR #354 - Make maxLines nullable +-- PR #349 - Add option for min number of chars before suggestionsCallback is called +-- PR #347 - Un private some variables +-- PR #347 - Fix deprecated info's in example +-- PR #344 - Add textAlignVertical support, fixes #231 + +## 3.2.2 - 20-Aug-2021 + +-- PR #333 - support Windows and MacOS by making keyboard_visibility optional + +## 3.2.1 - 10-Sept-2021 + +-- PR #327 - Added Scrollcontroler as optional parameter +-- PR #335 - Fix ErrorBuilder Widget display +-- PR #339 - Strong mode and type fixes + +## 3.2.0 - 9-Jul-2021 + +-- PR #326 - file structure reorganisation +-- PR #325 - Fix Scrollbar ScrollController + +## 3.1.3 - 7-May-2021 + +-- PR #308 - Allow suggestionsCallback to return null + +## 3.1.2 - 1-May-2021 + +-- PR #303 - Guard against missing size in \_adjustMaxHeightAndOrientation +-- PR #306 - Fixed Issue #286 - Suggestions callback called immediately + +## 3.1.1 - 28-March-2021 + +-- PR #297 - Fix styling of CHANGELOG.md + +## 3.1.0 - 21-March-2021 + +-- PR #295 - autoFillHints for TextFieldConfiguration +-- PR #294 - Check if the overlay is open +-- PR #292 - Various bug fixes, including null safety +-- PR #291 - Check for platform and run the correct example demo +-- PR #287 - Cancel the debounce timer when widget is destroyed +-- PR #285 - Fix possible race condition by doing an await + +## 3.0.0-nullsafety.0 - 9-Feburary-2021 + +-- PR #290 Null-safety pre-release + +## 2.0.0 - 11-January-2021 + +-- NOTE!! BREAKING CHANGE! Not major but changed Types for some calls +-- RE-APPLY : 1.9.2 will become 2.0.0 + +## 1.9.3 - 10-January-2021 + +-- REVERT : Reverting back to 1.9.1 as 1.9.3. 1.9.2 will become 2.0.0 + +## 1.9.2 - 06-January-2021 + +-- #267 : Remove undeeded typecasts and add String types + +## 1.9.1 - 03-December-2020 + +-- #256 : Change default to disabled for autovalidateMode and fix typo + +## 1.9.0 - 01-December-2020 + +- Merged 4 PRs: + -- #238 : Added hideKeyboard even if textfield has focus (edge case) + -- #248 : Added enabled and autovalidateMode properties. Resolves Issue #247 + -- #249 : Added enableSuggestions to Textfield Configuration. Resolves Issue #210 + -- #255 : Update to use flutter_keyboard_visibility 4.X from 3.X + +## 1.8.8 - 12-August-2020 + +- Merged PR to fix typo and validator tests and examples using deprecated consts. + +## 1.8.7 - 30-July-2020 + +- Merged PR to fix dispose() error in tests. + +## 1.8.6 - 05/07/2020 + +- Merged PR to fix "flashing" bug. + +## 1.8.5 - 01/07/2020 + +- Dependency Update : Updated flutter_Keyboard_visibility to ^3.0.0 from ^2.0.0 + +## 1.8.4 - 30/06/2020 + +- Bug Fix : Merged 3 PRs for various bug fixes. + +## 1.8.3 - 11/06/2020 + +- Bug Fix : PR to address keyboard visibility issues from @alphamikle + +## 1.8.1 - 08/04/2020 + +- Bug fixes + +## 1.8.0 - 23/01/2020 + +- Change from List to Iterable for flexibility +- Added `onTap` property to `TextFieldConfiguration` +- Added `offsetX` property to `SuggestionsBoxDecoration` and `CupertinoSuggestionsBoxDecoration` +- Support iOS 13 dark mode +- Bug fixes + +## 1.7.0 - 16/10/2019 + +- Updated keyboard_visibility dependency +- Scolling bug fix +- Added new property `enableInteractiveSelection` +- Fix disposing overlay + +Thanks to MisterJimson, davidmartos96, pparadox11, diegoveloper + +## 1.6.1 - 05/06/2019 + +- Fixed onChanged not being called for TypeAheadFormField + +## 1.6.0 - 19/05/2019 + +- Added CupertinoTypeAheadField for Cupertino users +- Updated example project +- Bug fixes + +## 1.5.0 - 25/04/2019 + +- Added `suggestionsBoxController` property and `SuggestionsBoxController` class to allow manual control of the suggestions box +- Fix suggestions box height problems in dialogs +- Add `textDirection` property to `TextFieldConfiguration` + +## 1.4.1 - 09/04/2019 + +- Fixed BoxConstraints width parameters being ignored in `SuggestionsBoxDecoration` + +## 1.4.0 - 26/03/2019 + +- Added property `autoFlipDirection` to allow automatic direction flipping if + there is not enough space for the suggestions list + +## 1.3.0 - 19/03/2019 + +- Limit number of suggestionsCallbacks until current call is finished + +## 1.2.1 - 19/03/2019 + +- Bug fixes & optimizations + +## 1.2.0 - 05/03/2019 + +- Added property `keepSuggestionsOnLoading` +- Changed default behavior: suggestions box will no longer + show circular progress indicator when loading; it will maintain previous results if available + +## 1.1.0 - 01/03/2019 + +- Suggestions box now closes on keyboard hide by default +- Added property `hideSuggestionsOnKeyboardHide` +- Width now properly resizes on orientation changes +- Suggestions box will display above keyboard when keyboard hides the box for AxisDirection.Up +- Fix FocusNode errors +- Fix keyboard height calculation + +## 1.0.4/5 - 21/02/2019 + +- Fix suggestions being called on TextBox focus + +## 1.0.3 - 12/02/2019 + +- Resize suggestion box when scrolling + +## 1.0.2 - 07/02/2019 + +- Bug fix for `maxHeight` property + +## 1.0.1 - 06/02/2019 + +- Added properties `hideOnLoading`, `hideOnEmpty`, and `hideOnError` to hide the suggestions box + +## 0.6.1 - 26/01/2019 + +- Allow types to properly work. +- Add documentation for direction: option. + +## 0.6.0 - 23/01/2019 + +- Added property `direction` to allow the suggestions to grow either up or down + +## 0.5.2 - 19/01/2019 + +- Added contributing guidelines and reverse sorted the CHANGLELOG.md file. + +## 0.5.1 - 10/01/2019 + +- Bug fixes + +## 0.5.0 - 05/01/2019 + +- Added the hasScrollbar property which allows the optional display of a `Scrollbar` +- Fixed the case where the suggestion box becomes hidden behind the keyboard +- Fixed the bug of not disposing the animations controller + +## 0.4.1 - 20/09/2018 + +- Added property `getImmediateSuggestions` to the form field implementation + +## 0.4.0 - 20/09/2018 + +- Added property `getImmediateSuggestions` to allow fetching + suggestions before the user types +- Added assertion in the form field to disallow having `initialValue` + and `textFieldConfiguration.controller` defined at the same time + +## 0.3.0 - 15/09/2018 + +- Added a constraints property to the `SuggestionsBoxDecorations` + which allows to set the height and width of the suggestions box + +## 0.2.1 - 04/09/2018 + +- Added mention of 'autocomplete' in README and pubspec +- Executed 'flutter format' + +## 0.2.0 - 02/09/2018 + +- Changed the suggestions box decoration + to decorate a material sheet instead of + decorating a container +- Moved the `TextField` properties inside a class + called `TextFieldConfiguration`, which is provided + to the `TypeAhead` widgets through a + `textFieldConfiguration` property. This was done to + decrease the clutter in the interface +- Added more configuration properties to the + `TextField` +- Added a configurable vertical offset for the + suggestions box +- Changed the mechanism used to open/close the suggestions box +- Added meta-tags to README for SEO +- Updated the GIF to show the changes +- Added "How you can help" section to README + +## 0.1.2 - 31/08/2018 + +- Small fix to README + +## 0.1.1 - 31/08/2018 + +- Fixed CHANGELOG. +- Small fix to documentation + +## 0.1.0 - 31/08/2018 + +- Initial Release. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..63d4ddc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,40 @@ +# Contributing to TypeAheadField + +## Create a new issue + +The easiest way to get involved is to create a [new issue](https://github.com/AbdulRahmanAlHamali/flutter_typeahead/issues/new) when you spot a bug, if the documentation is incomplete or out of date, or if you identify an implementation problem. + +## Modifying Code + +If you plan to submit a PR please do the following: + +- Fork the repository +- Create a feature branch from the **master** branch! +- Following the coding guidlines below +- Submit the PR against the **master** branch. +- Update both Material and Cupertino code if applicable + +## General coding guidlines + +If you'd like to add a feature or fix a bug, we're more than happy to accept pull requests! We only ask a few things: + +- Ensure your code contains no analyzer errors, e.g. + - Code is strong-mode compliant + - Code is free of lint errors +- Format your code with `dartfmt` +- Write helpful documentation +- Write new tests that cover your code base changes +- Make sure all current tests pass +- If you would like to make a bigger / fundamental change to the codebase, please file a lightweight example PR / issue. + +## Before Uploading + +If you are an uploader here are some additional steps before publishing. + +- Update the version: + - if it is only a bug fix, increase the last digit. + - if it provides a new feature, increase the middle digit. + - if it has breaking changes, you should increase the first digit. +- Then, mention all the changes in the CHANGELOG.md. +- Merge into master. +- Upload to Pub Dart. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1ecc7e6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +BSD 2-Clause License + +Copyright (c) 2018, AbdulRahmanAlHamali +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ca6d4a5 --- /dev/null +++ b/README.md @@ -0,0 +1,327 @@ + + +[![Pub](https://img.shields.io/pub/v/flutter_typeahead)](https://pub.dev/packages/flutter_typeahead) + +# Flutter TypeAhead +A TypeAhead (autocomplete) widget for Flutter, where you can show suggestions to +users as they type + + + +## Features +* Shows suggestions in an overlay that floats on top of other widgets +* Allows you to specify what the suggestions will look like through a +builder function +* Allows you to specify what happens when the user taps a suggestion +* Accepts all the parameters that traditional TextFields accept, like +decoration, custom TextEditingController, text styling, etc. +* Provides two versions, a normal version and a [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +version that accepts validation, submitting, etc. +* Provides high customizable; you can customize the suggestion box decoration, +the loading bar, the animation, the debounce duration, etc. + +## Installation +See the [installation instructions on pub](https://pub.dartlang.org/packages/flutter_typeahead#-installing-tab-). + +Note: As for Typeahead 3.X this package is based on Dart 2.12 (null-safety). You may also want to explore the new built in Flutter 2 widgets that have similar behavior. + +## Usage examples +You can import the package with: +```dart +import 'package:flutter_typeahead/flutter_typeahead.dart'; +``` + +For Cupertino users import: +```dart +import 'package:flutter_typeahead/cupertino_flutter_typeahead.dart'; +``` + +Use it as follows: + +### Material Example 1: +```dart +TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + autofocus: true, + style: DefaultTextStyle.of(context).style.copyWith( + fontStyle: FontStyle.italic + ), + decoration: InputDecoration( + border: OutlineInputBorder() + ) + ), + suggestionsCallback: (pattern) async { + return await BackendService.getSuggestions(pattern); + }, + itemBuilder: (context, suggestion) { + return ListTile( + leading: Icon(Icons.shopping_cart), + title: Text(suggestion['name']), + subtitle: Text('\$${suggestion['price']}'), + ); + }, + onSuggestionSelected: (suggestion) { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => ProductPage(product: suggestion) + )); + }, +) +``` +In the code above, the `textFieldConfiguration` property allows us to +configure the displayed `TextField` as we want. In this example, we are +configuring the `autofocus`, `style` and `decoration` properties. + +The `suggestionsCallback` is called with the search string that the user +types, and is expected to return a `List` of data either synchronously or +asynchronously. In this example, we are calling an asynchronous function +called `BackendService.getSuggestions` which fetches the list of +suggestions. + +The `itemBuilder` is called to build a widget for each suggestion. +In this example, we build a simple `ListTile` that shows the name and the +price of the item. Please note that you shouldn't provide an `onTap` +callback here. The TypeAhead widget takes care of that. + +The `onSuggestionSelected` is a callback called when the user taps a +suggestion. In this example, when the user taps a +suggestion, we navigate to a page that shows us the information of the +tapped product. + +### Material Example 2: +Here's another example, where we use the TypeAheadFormField inside a `Form`: +```dart +final GlobalKey _formKey = GlobalKey(); +final TextEditingController _typeAheadController = TextEditingController(); +String _selectedCity; +... +Form( + key: this._formKey, + child: Padding( + padding: EdgeInsets.all(32.0), + child: Column( + children: [ + Text( + 'What is your favorite city?' + ), + TypeAheadFormField( + textFieldConfiguration: TextFieldConfiguration( + controller: this._typeAheadController, + decoration: InputDecoration( + labelText: 'City' + ) + ), + suggestionsCallback: (pattern) { + return CitiesService.getSuggestions(pattern); + }, + itemBuilder: (context, suggestion) { + return ListTile( + title: Text(suggestion), + ); + }, + transitionBuilder: (context, suggestionsBox, controller) { + return suggestionsBox; + }, + onSuggestionSelected: (suggestion) { + this._typeAheadController.text = suggestion; + }, + validator: (value) { + if (value.isEmpty) { + return 'Please select a city'; + } + }, + onSaved: (value) => this._selectedCity = value, + ), + SizedBox(height: 10.0,), + RaisedButton( + child: Text('Submit'), + onPressed: () { + if (this._formKey.currentState.validate()) { + this._formKey.currentState.save(); + Scaffold.of(context).showSnackBar(SnackBar( + content: Text('Your Favorite City is ${this._selectedCity}') + )); + } + }, + ) + ], + ), + ), +) +``` +Here, we assign to the `controller` property of the `textFieldConfiguration` +a `TextEditingController` that we call `_typeAheadController`. +We use this controller in the `onSuggestionSelected` callback to set the +value of the `TextField` to the selected suggestion. + +The `validator` callback can be used like any `FormField.validator` +function. In our example, it checks whether a value has been entered, +and displays an error message if not. The `onSaved` callback is used to +save the value of the field to the `_selectedCity` member variable. + +The `transitionBuilder` allows us to customize the animation of the +suggestion box. In this example, we are returning the suggestionsBox +immediately, meaning that we don't want any animation. + +### Cupertino Example: +Please see the Cupertino code in the example project. + +## Known Issues + +### Animations +Placing TypeAheadField in widgets with animations may cause the suggestions box +to resize incorrectly. Since animation times are variable, this has to be +corrected manually at the end of the animation. You will need to add a +SuggestionsBoxController described below and the following code for the +AnimationController. +```dart +void Function(AnimationStatus) _statusListener; + +@override +void initState() { + super.initState(); + _statusListener = (AnimationStatus status) { + if (status == AnimationStatus.completed || + status == AnimationStatus.dismissed) { + _suggestionsBoxController.resize(); + } + }; + + _animationController.addStatusListener(_statusListener); +} + +@override + void dispose() { + _animationController.removeStatusListener(_statusListener); + _animationController.dispose(); + super.dispose(); +} +``` + +#### Dialogs +There is a known issue with opening dialogs where the suggestions box will sometimes appear too small. This is a timing issue caused by the animations described above. Currently, `showDialog` has a duration of 150 ms for the animations. TypeAheadField has a delay of 170 ms to compensate for this. Until the end of the animation can be properly detected and fixed using the solution above, this temporary fix will work most of the time. If the suggestions box is too small, closing and reopening the keyboard will usually fix the issue. + +### Cupertino +The Cupertino classes in TypeAhead are still new. There are also differences in the Cupertino widgets vs the Material ones. Some behavior will not translate when moving between the two. + +## Customizations +TypeAhead widgets consist of a TextField and a suggestion box that shows +as the user types. Both are highly customizable + +### Customizing the TextField +You can customize the text field using the `textFieldConfiguration` property. +You provide this property with an instance of `TextFieldConfiguration`, +which allows you to configure all the usual properties of `TextField`, like +`decoration`, `style`, `controller`, `focusNode`, `autofocus`, `enabled`, +etc. + +### Customizing the suggestions box +TypeAhead provides default configurations for the suggestions box. You can, +however, override most of them. This is done by passing a `SuggestionsBoxDecoration` +to the `suggestionsBoxDecoration` property. + +Use the `offsetX` property in `SuggestionsBoxDecoration` to shift the suggestions box along the x-axis. +You may also pass BoxConstraints to `constraints` in `SuggestionsBoxDecoration` to adjust the width +and height of the suggestions box. Using the two together will allow the suggestions box to be placed +almost anywhere. + +#### Customizing the loader, the error and the "no items found" message +You can use the `loadingBuilder`, `errorBuilder` and `noItemsFoundBuilder` to +customize their corresponding widgets. For example, to show a custom error +widget: +```dart +errorBuilder: (BuildContext context, Object error) => + Text( + '$error', + style: TextStyle( + color: Theme.of(context).errorColor + ) + ) +``` + +By default, the suggestions box will maintain the old suggestions while new +suggestions are being retrieved. To show a circular progress indicator +during retrieval instead, set `keepSuggestionsOnLoading` to false. + +#### Hiding the suggestions box +There are three scenarios when you can hide the suggestions box. + +Set `hideOnLoading` to true to hide the box while suggestions are being +retrieved. This will also ignore the `loadingBuilder`. Set `hideOnEmpty` +to true to hide the box when there are no suggestions. This will also ignore +the `noItemsFoundBuilder`. Set `hideOnError` to true to hide the box when there +is an error retrieving suggestions. This will also ignore the `errorBuilder`. + +By default, the suggestions box will automatically hide when the keyboard is hidden. +To change this behavior, set `hideSuggestionsOnKeyboardHide` to false. + +#### Customizing the animation +You can customize the suggestion box animation through 3 parameters: the +`animationDuration`, the `animationStart`, and the `transitionBuilder`. + +The `animationDuration` specifies how long the animation should take, while the +`animationStart` specified what point (between 0.0 and 1.0) the animation +should start from. The `transitionBuilder` accepts the `suggestionsBox` and +`animationController` as parameters, and should return a widget that uses +the `animationController` to animate the display of the `suggestionsBox`. +For example: +```dart +transitionBuilder: (context, suggestionsBox, animationController) => + FadeTransition( + child: suggestionsBox, + opacity: CurvedAnimation( + parent: animationController, + curve: Curves.fastOutSlowIn + ), + ) +``` +This uses [FadeTransition](https://docs.flutter.io/flutter/widgets/FadeTransition-class.html) +to fade the `suggestionsBox` into the view. Note how the +`animationController` was provided as the parent of the animation. + +In order to fully remove the animation, `transitionBuilder` should simply +return the `suggestionsBox`. This callback could also be used to wrap the +`suggestionsBox` with any desired widgets, not necessarily for animation. + +#### Customizing the debounce duration +The suggestions box does not fire for each character the user types. Instead, +we wait until the user is idle for a duration of time, and then call the +`suggestionsCallback`. The duration defaults to 300 milliseconds, but can be +configured using the `debounceDuration` parameter. + +#### Customizing the offset of the suggestions box +By default, the suggestions box is displayed 5 pixels below the `TextField`. +You can change this by changing the `suggestionsBoxVerticalOffset` property. + +#### Customizing the decoration of the suggestions box +You can also customize the decoration of the suggestions box using the +`suggestionsBoxDecoration` property. For example, to remove the elevation +of the suggestions box, you can write: +```dart +suggestionsBoxDecoration: SuggestionsBoxDecoration( + elevation: 0.0 +) +``` + +#### Customizing the growth direction of the suggestions list +By default, the list grows towards the bottom. However, you can use the `direction` property to customize the growth direction to be one of `AxisDirection.down` or `AxisDirection.up`, the latter of which will cause the list to grow up, where the first suggestion is at the bottom of the list, and the last suggestion is at the top. + +Set `autoFlipDirection` to true to allow the suggestions list to automatically flip direction whenever it detects that there is not enough space for the current direction. This is useful for scenarios where the TypeAheadField is in a scrollable widget or when the developer wants to ensure the list is always viewable despite different user screen sizes. + +#### Controlling the suggestions box +Manual control of the suggestions box can be achieved by creating an instance of `SuggestionsBoxController` and +passing it to the `suggestionsBoxController` property. This will allow you to manually open, close, toggle, or +resize the suggestions box. + +## For more information +Visit the [API Documentation](https://pub.dartlang.org/documentation/flutter_typeahead/latest/) + +## Team: +| [](https://github.com/AbdulRahmanAlHamali)|[](https://github.com/sjmcdowall)|[](https://github.com/KaYBlitZ)| +|---|---|---| +|AbdulRahman AlHamali|S McDowall|Kenneth Liang| + +## Shout out to the contributors! +This project is the result of the collective effort of contributors who participated effectively by submitting pull requests, reporting issues, and answering questions. Thank you for your proactiveness, and we hope flutter_typeahead made your lifes at least a little easier! + +## How you can help +[Contribution Guidelines](https://github.com/AbdulRahmanAlHamali/flutter_typeahead/blob/master/CONTRIBUTING.md) diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..4135297 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,4 @@ +analyzer: + strong-mode: + implicit-casts: false + implicit-dynamic: false diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..0fa6b67 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/example/.metadata b/example/.metadata new file mode 100644 index 0000000..92fd7de --- /dev/null +++ b/example/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled. + +version: + revision: cd41fdd495f6944ecd3506c21e94c6567b073278 + channel: stable + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278 + base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278 + - platform: web + create_revision: cd41fdd495f6944ecd3506c21e94c6567b073278 + base_revision: cd41fdd495f6944ecd3506c21e94c6567b073278 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..a135626 --- /dev/null +++ b/example/README.md @@ -0,0 +1,16 @@ +# example + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/example/android/.gitignore b/example/android/.gitignore new file mode 100644 index 0000000..0a741cb --- /dev/null +++ b/example/android/.gitignore @@ -0,0 +1,11 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle new file mode 100644 index 0000000..86d5ab4 --- /dev/null +++ b/example/android/app/build.gradle @@ -0,0 +1,59 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.example" + minSdkVersion 16 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3da38e3 --- /dev/null +++ b/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000..e793a00 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..449a9f9 --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..d74aa35 --- /dev/null +++ b/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..c208884 --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle new file mode 100644 index 0000000..2d58113 --- /dev/null +++ b/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.7.10' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.3' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cc5527d --- /dev/null +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/ios/.gitignore b/example/ios/.gitignore new file mode 100644 index 0000000..e96ef60 --- /dev/null +++ b/example/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..9625e10 --- /dev/null +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 11.0 + + diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..ec97fc6 --- /dev/null +++ b/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/example/ios/Podfile b/example/ios/Podfile new file mode 100644 index 0000000..88359b2 --- /dev/null +++ b/example/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '11.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 0000000..3091738 --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,22 @@ +PODS: + - Flutter (1.0.0) + - flutter_keyboard_visibility (0.0.1): + - Flutter + +DEPENDENCIES: + - Flutter (from `Flutter`) + - flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`) + +EXTERNAL SOURCES: + Flutter: + :path: Flutter + flutter_keyboard_visibility: + :path: ".symlinks/plugins/flutter_keyboard_visibility/ios" + +SPEC CHECKSUMS: + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 + flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069 + +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 + +COCOAPODS: 1.11.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a3f2352 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,550 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0AA0FD8F2BCB1D02A381FA2C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 070C64CE3E3829B4B69F6D65 /* Pods_Runner.framework */; }; + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 05D429632D8FD2830C666F9D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 070C64CE3E3829B4B69F6D65 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 5AF13D361E4357D2A725E8B9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D80F953CFD9EF627D227F3B1 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0AA0FD8F2BCB1D02A381FA2C /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 78354FCE6CD6437F846D905F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 070C64CE3E3829B4B69F6D65 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + DEA2152EEB1D8575D5DFDC3C /* Pods */, + 78354FCE6CD6437F846D905F /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + DEA2152EEB1D8575D5DFDC3C /* Pods */ = { + isa = PBXGroup; + children = ( + D80F953CFD9EF627D227F3B1 /* Pods-Runner.debug.xcconfig */, + 5AF13D361E4357D2A725E8B9 /* Pods-Runner.release.xcconfig */, + 05D429632D8FD2830C666F9D /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 23424392682879E6F903E036 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + B873A209970BF6D2B0E8E9D1 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 23424392682879E6F903E036 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + B873A209970BF6D2B0E8E9D1 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..3db53b6 --- /dev/null +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +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. \ No newline at end of file diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist new file mode 100644 index 0000000..4f68a2c --- /dev/null +++ b/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/example/lib/main.dart b/example/lib/main.dart new file mode 100644 index 0000000..5b926bb --- /dev/null +++ b/example/lib/main.dart @@ -0,0 +1,383 @@ +import 'dart:async'; +import 'dart:io' show Platform; +import 'dart:math'; +import 'dart:ui'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; + +void main() => runApp(MyApp()); + +class MyApp extends StatefulWidget { + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + bool isCupertino = !kIsWeb && Platform.isIOS; + + @override + Widget build(BuildContext context) { + if (!isCupertino) { + return MaterialApp( + title: 'flutter_typeahead demo', + scrollBehavior: + MaterialScrollBehavior().copyWith(dragDevices: {PointerDeviceKind.mouse, PointerDeviceKind.touch}), + home: DefaultTabController( + length: 3, + child: Scaffold( + appBar: AppBar( + leading: IconButton( + icon: Icon(Icons.phone_iphone), + onPressed: () => setState(() { + isCupertino = true; + }), + ), + title: TabBar(tabs: [ + Tab(text: 'Example 1: Navigation'), + Tab(text: 'Example 2: Form'), + Tab(text: 'Example 3: Scroll') + ]), + ), + body: GestureDetector( + onTap: () => FocusScope.of(context).unfocus(), + child: TabBarView(children: [ + NavigationExample(), + FormExample(), + ScrollExample(), + ]), + )), + ), + ); + } else { + return CupertinoApp( + title: 'Cupertino demo', + home: Scaffold( + appBar: CupertinoNavigationBar( + leading: IconButton( + icon: Icon(Icons.android), + onPressed: () => setState(() { + isCupertino = false; + }), + ), + middle: Text('Cupertino demo'), + ), + body: CupertinoPageScaffold( + child: FavoriteCitiesPage(), + ), + ), //MyHomePage(), + ); + } + } +} + +class NavigationExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.all(32.0), + child: Column( + children: [ + SizedBox( + height: 10.0, + ), + TypeAheadField( + textFieldConfiguration: TextFieldConfiguration( + autofocus: true, + style: DefaultTextStyle.of(context).style.copyWith(fontStyle: FontStyle.italic), + decoration: InputDecoration(border: OutlineInputBorder(), hintText: 'What are you looking for?'), + ), + suggestionsCallback: (pattern) async { + return await BackendService.getSuggestions(pattern); + }, + itemBuilder: (context, Map suggestion) { + return ListTile( + leading: Icon(Icons.shopping_cart), + title: Text(suggestion['name']!), + subtitle: Text('\$${suggestion['price']}'), + ); + }, + onSuggestionSelected: (Map suggestion) { + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => ProductPage(product: suggestion))); + }, + suggestionsBoxDecoration: SuggestionsBoxDecoration( + borderRadius: BorderRadius.circular(10.0), + elevation: 8.0, + color: Theme.of(context).cardColor, + ), + ), + ], + ), + ); + } +} + +class FormExample extends StatefulWidget { + @override + _FormExampleState createState() => _FormExampleState(); +} + +class _FormExampleState extends State { + final GlobalKey _formKey = GlobalKey(); + final TextEditingController _typeAheadController = TextEditingController(); + + String? _selectedCity; + + SuggestionsBoxController suggestionBoxController = SuggestionsBoxController(); + + @override + Widget build(BuildContext context) { + return GestureDetector( + // close the suggestions box when the user taps outside of it + onTap: () { + suggestionBoxController.close(); + }, + child: Container( + // Add zero opacity to make the gesture detector work + color: Colors.amber.withOpacity(0), + // Create the form for the user to enter their favorite city + child: Form( + key: this._formKey, + child: Padding( + padding: EdgeInsets.all(32.0), + child: Column( + children: [ + Text('What is your favorite city?'), + TypeAheadFormField( + textFieldConfiguration: TextFieldConfiguration( + decoration: InputDecoration(labelText: 'City'), + controller: this._typeAheadController, + ), + suggestionsCallback: (pattern) { + return CitiesService.getSuggestions(pattern); + }, + itemBuilder: (context, String suggestion) { + return ListTile( + title: Text(suggestion), + ); + }, + transitionBuilder: (context, suggestionsBox, controller) { + return suggestionsBox; + }, + onSuggestionSelected: (String suggestion) { + this._typeAheadController.text = suggestion; + }, + suggestionsBoxController: suggestionBoxController, + validator: (value) => value!.isEmpty ? 'Please select a city' : null, + onSaved: (value) => this._selectedCity = value, + ), + Spacer(), + ElevatedButton( + child: Text('Submit'), + onPressed: () { + if (this._formKey.currentState!.validate()) { + this._formKey.currentState!.save(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Your Favorite City is ${this._selectedCity}'), + ), + ); + } + }, + ) + ], + ), + ), + ), + ), + ); + } +} + +class ProductPage extends StatelessWidget { + final Map product; + + ProductPage({required this.product}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: const EdgeInsets.all(50.0), + child: Column( + children: [ + Text( + this.product['name']!, + style: Theme.of(context).textTheme.headlineSmall, + ), + Text( + this.product['price']! + ' USD', + style: Theme.of(context).textTheme.titleMedium, + ) + ], + ), + ), + ); + } +} + +/// This example shows how to use the [TypeAheadField] in a [ListView] that +/// scrolls. The [TypeAheadField] will resize to fit the suggestions box when +/// scrolling. +class ScrollExample extends StatelessWidget { + final List items = List.generate(50, (index) => "Item $index"); + + @override + Widget build(BuildContext context) { + return ListView(children: [ + Center( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Suggestion box will resize when scrolling"), + ), + ), + SizedBox(height: 200), + TypeAheadField( + getImmediateSuggestions: true, + textFieldConfiguration: TextFieldConfiguration( + decoration: InputDecoration(border: OutlineInputBorder(), hintText: 'What are you looking for?'), + ), + suggestionsCallback: (String pattern) async { + return items.where((item) => item.toLowerCase().startsWith(pattern.toLowerCase())).toList(); + }, + itemBuilder: (context, String suggestion) { + return ListTile( + title: Text(suggestion), + ); + }, + onSuggestionSelected: (String suggestion) { + print("Suggestion selected"); + }, + ), + SizedBox(height: 500), + ]); + } +} + +/// This is a fake service that mimics a backend service. +/// It returns a list of suggestions after a 1 second delay. +/// In a real app, this would be a service that makes a network request. +class BackendService { + static Future>> getSuggestions(String query) async { + await Future.delayed(Duration(seconds: 1)); + + return List.generate(3, (index) { + return {'name': query + index.toString(), 'price': Random().nextInt(100).toString()}; + }); + } +} + +/// A fake service to filter cities based on a query. +class CitiesService { + static final List cities = [ + 'Beirut', + 'Damascus', + 'San Fransisco', + 'Rome', + 'Los Angeles', + 'Madrid', + 'Bali', + 'Barcelona', + 'Paris', + 'Bucharest', + 'New York City', + 'Philadelphia', + 'Sydney', + ]; + + static List getSuggestions(String query) { + List matches = []; + matches.addAll(cities); + + matches.retainWhere((s) => s.toLowerCase().contains(query.toLowerCase())); + return matches; + } +} + +class FavoriteCitiesPage extends StatefulWidget { + @override + _FavoriteCitiesPage createState() => _FavoriteCitiesPage(); +} + +class _FavoriteCitiesPage extends State { + final GlobalKey _formKey = GlobalKey(); + final TextEditingController _typeAheadController = TextEditingController(); + CupertinoSuggestionsBoxController _suggestionsBoxController = CupertinoSuggestionsBoxController(); + String favoriteCity = 'Unavailable'; + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => _suggestionsBoxController.close(), + child: Container( + color: Colors.amber.withOpacity(0), + child: Form( + key: _formKey, + child: Padding( + padding: EdgeInsets.all(32.0), + child: Column( + children: [ + SizedBox( + height: 100.0, + ), + Text('What is your favorite city?'), + CupertinoTypeAheadFormField( + getImmediateSuggestions: true, + suggestionsBoxController: _suggestionsBoxController, + suggestionsBoxDecoration: CupertinoSuggestionsBoxDecoration( + borderRadius: BorderRadius.circular(8.0), + ), + textFieldConfiguration: CupertinoTextFieldConfiguration( + controller: _typeAheadController, + ), + suggestionsCallback: (pattern) { + return Future.delayed( + Duration(seconds: 1), + () => CitiesService.getSuggestions(pattern), + ); + }, + itemBuilder: (context, String suggestion) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: Text( + suggestion, + ), + ); + }, + onSuggestionSelected: (String suggestion) { + _typeAheadController.text = suggestion; + }, + validator: (value) => value!.isEmpty ? 'Please select a city' : null, + ), + SizedBox( + height: 10.0, + ), + CupertinoButton( + child: Text('Submit'), + onPressed: () { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + setState(() { + favoriteCity = _typeAheadController.text; + }); + } + }, + ), + SizedBox( + height: 10.0, + ), + Text( + 'Your favorite city is $favoriteCity!', + textAlign: TextAlign.center, + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/example/linux/.gitignore b/example/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/example/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/example/linux/CMakeLists.txt b/example/linux/CMakeLists.txt new file mode 100644 index 0000000..a558bc4 --- /dev/null +++ b/example/linux/CMakeLists.txt @@ -0,0 +1,116 @@ +cmake_minimum_required(VERSION 3.10) +project(runner LANGUAGES CXX) + +set(BINARY_NAME "example") +set(APPLICATION_ID "com.example.example") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Configure build options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Application build +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) +apply_standard_settings(${BINARY_NAME}) +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) +add_dependencies(${BINARY_NAME} flutter_assemble) +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/example/linux/flutter/CMakeLists.txt b/example/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..6dc9705 --- /dev/null +++ b/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,91 @@ +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) +pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid) +pkg_check_modules(LZMA REQUIRED IMPORTED_TARGET liblzma) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO + PkgConfig::BLKID + PkgConfig::LZMA +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..e71a16d --- /dev/null +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/example/linux/flutter/generated_plugin_registrant.h b/example/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/example/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..2e1de87 --- /dev/null +++ b/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/example/linux/main.cc b/example/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/example/linux/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/example/linux/my_application.cc b/example/linux/my_application.cc new file mode 100644 index 0000000..634f4c5 --- /dev/null +++ b/example/linux/my_application.cc @@ -0,0 +1,105 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen *screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } + else { + gtk_window_set_title(window, "example"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject *object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/example/linux/my_application.h b/example/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/example/linux/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 0000000..d8bd5fa --- /dev/null +++ b/example/pubspec.yaml @@ -0,0 +1,78 @@ +name: example +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.12.0-0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + flutter_typeahead: + path: ../ + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/example/web/favicon.png b/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-192.png b/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 zcmZ`-2T+sGz6~)*FVZ`aW+(v>MIm&M-g^@e2u-B-DoB?qO+b1Tq<5uCCv>ESfRum& zp%X;f!~1{tzL__3=gjVJ=j=J>+nMj%ncXj1Q(b|Ckbw{Y0FWpt%4y%$uD=Z*c-x~o zE;IoE;xa#7Ll5nj-e4CuXB&G*IM~D21rCP$*xLXAK8rIMCSHuSu%bL&S3)8YI~vyp@KBu9Ph7R_pvKQ@xv>NQ`dZp(u{Z8K3yOB zn7-AR+d2JkW)KiGx0hosml;+eCXp6+w%@STjFY*CJ?udJ64&{BCbuebcuH;}(($@@ znNlgBA@ZXB)mcl9nbX#F!f_5Z=W>0kh|UVWnf!At4V*LQP%*gPdCXd6P@J4Td;!Ur z<2ZLmwr(NG`u#gDEMP19UcSzRTL@HsK+PnIXbVBT@oHm53DZr?~V(0{rsalAfwgo zEh=GviaqkF;}F_5-yA!1u3!gxaR&Mj)hLuj5Q-N-@Lra{%<4ONja8pycD90&>yMB` zchhd>0CsH`^|&TstH-8+R`CfoWqmTTF_0?zDOY`E`b)cVi!$4xA@oO;SyOjJyP^_j zx^@Gdf+w|FW@DMdOi8=4+LJl$#@R&&=UM`)G!y%6ZzQLoSL%*KE8IO0~&5XYR9 z&N)?goEiWA(YoRfT{06&D6Yuu@Qt&XVbuW@COb;>SP9~aRc+z`m`80pB2o%`#{xD@ zI3RAlukL5L>px6b?QW1Ac_0>ew%NM!XB2(H+1Y3AJC?C?O`GGs`331Nd4ZvG~bMo{lh~GeL zSL|tT*fF-HXxXYtfu5z+T5Mx9OdP7J4g%@oeC2FaWO1D{=NvL|DNZ}GO?O3`+H*SI z=grGv=7dL{+oY0eJFGO!Qe(e2F?CHW(i!!XkGo2tUvsQ)I9ev`H&=;`N%Z{L zO?vV%rDv$y(@1Yj@xfr7Kzr<~0{^T8wM80xf7IGQF_S-2c0)0D6b0~yD7BsCy+(zL z#N~%&e4iAwi4F$&dI7x6cE|B{f@lY5epaDh=2-(4N05VO~A zQT3hanGy_&p+7Fb^I#ewGsjyCEUmSCaP6JDB*=_()FgQ(-pZ28-{qx~2foO4%pM9e z*_63RT8XjgiaWY|*xydf;8MKLd{HnfZ2kM%iq}fstImB-K6A79B~YoPVa@tYN@T_$ zea+9)<%?=Fl!kd(Y!G(-o}ko28hg2!MR-o5BEa_72uj7Mrc&{lRh3u2%Y=Xk9^-qa zBPWaD=2qcuJ&@Tf6ue&)4_V*45=zWk@Z}Q?f5)*z)-+E|-yC4fs5CE6L_PH3=zI8p z*Z3!it{1e5_^(sF*v=0{`U9C741&lub89gdhKp|Y8CeC{_{wYK-LSbp{h)b~9^j!s z7e?Y{Z3pZv0J)(VL=g>l;<}xk=T*O5YR|hg0eg4u98f2IrA-MY+StQIuK-(*J6TRR z|IM(%uI~?`wsfyO6Tgmsy1b3a)j6M&-jgUjVg+mP*oTKdHg?5E`!r`7AE_#?Fc)&a z08KCq>Gc=ne{PCbRvs6gVW|tKdcE1#7C4e`M|j$C5EYZ~Y=jUtc zj`+?p4ba3uy7><7wIokM79jPza``{Lx0)zGWg;FW1^NKY+GpEi=rHJ+fVRGfXO zPHV52k?jxei_!YYAw1HIz}y8ZMwdZqU%ESwMn7~t zdI5%B;U7RF=jzRz^NuY9nM)&<%M>x>0(e$GpU9th%rHiZsIT>_qp%V~ILlyt^V`=d z!1+DX@ah?RnB$X!0xpTA0}lN@9V-ePx>wQ?-xrJr^qDlw?#O(RsXeAvM%}rg0NT#t z!CsT;-vB=B87ShG`GwO;OEbeL;a}LIu=&@9cb~Rsx(ZPNQ!NT7H{@j0e(DiLea>QD zPmpe90gEKHEZ8oQ@6%E7k-Ptn#z)b9NbD@_GTxEhbS+}Bb74WUaRy{w;E|MgDAvHw zL)ycgM7mB?XVh^OzbC?LKFMotw3r@i&VdUV%^Efdib)3@soX%vWCbnOyt@Y4swW925@bt45y0HY3YI~BnnzZYrinFy;L?2D3BAL`UQ zEj))+f>H7~g8*VuWQ83EtGcx`hun$QvuurSMg3l4IP8Fe`#C|N6mbYJ=n;+}EQm;< z!!N=5j1aAr_uEnnzrEV%_E|JpTb#1p1*}5!Ce!R@d$EtMR~%9# zd;h8=QGT)KMW2IKu_fA_>p_und#-;Q)p%%l0XZOXQicfX8M~7?8}@U^ihu;mizj)t zgV7wk%n-UOb z#!P5q?Ex+*Kx@*p`o$q8FWL*E^$&1*!gpv?Za$YO~{BHeGY*5%4HXUKa_A~~^d z=E*gf6&+LFF^`j4$T~dR)%{I)T?>@Ma?D!gi9I^HqvjPc3-v~=qpX1Mne@*rzT&Xw zQ9DXsSV@PqpEJO-g4A&L{F&;K6W60D!_vs?Vx!?w27XbEuJJP&);)^+VF1nHqHBWu z^>kI$M9yfOY8~|hZ9WB!q-9u&mKhEcRjlf2nm_@s;0D#c|@ED7NZE% zzR;>P5B{o4fzlfsn3CkBK&`OSb-YNrqx@N#4CK!>bQ(V(D#9|l!e9(%sz~PYk@8zt zPN9oK78&-IL_F zhsk1$6p;GqFbtB^ZHHP+cjMvA0(LqlskbdYE_rda>gvQLTiqOQ1~*7lg%z*&p`Ry& zRcG^DbbPj_jOKHTr8uk^15Boj6>hA2S-QY(W-6!FIq8h$<>MI>PYYRenQDBamO#Fv zAH5&ImqKBDn0v5kb|8i0wFhUBJTpT!rB-`zK)^SNnRmLraZcPYK7b{I@+}wXVdW-{Ps17qdRA3JatEd?rPV z4@}(DAMf5EqXCr4-B+~H1P#;t@O}B)tIJ(W6$LrK&0plTmnPpb1TKn3?f?Kk``?D+ zQ!MFqOX7JbsXfQrz`-M@hq7xlfNz;_B{^wbpG8des56x(Q)H)5eLeDwCrVR}hzr~= zM{yXR6IM?kXxauLza#@#u?Y|o;904HCqF<8yT~~c-xyRc0-vxofnxG^(x%>bj5r}N zyFT+xnn-?B`ohA>{+ZZQem=*Xpqz{=j8i2TAC#x-m;;mo{{sLB_z(UoAqD=A#*juZ zCv=J~i*O8;F}A^Wf#+zx;~3B{57xtoxC&j^ie^?**T`WT2OPRtC`xj~+3Kprn=rVM zVJ|h5ux%S{dO}!mq93}P+h36mZ5aZg1-?vhL$ke1d52qIiXSE(llCr5i=QUS?LIjc zV$4q=-)aaR4wsrQv}^shL5u%6;`uiSEs<1nG^?$kl$^6DL z43CjY`M*p}ew}}3rXc7Xck@k41jx}c;NgEIhKZ*jsBRZUP-x2cm;F1<5$jefl|ppO zmZd%%?gMJ^g9=RZ^#8Mf5aWNVhjAS^|DQO+q$)oeob_&ZLFL(zur$)); zU19yRm)z<4&4-M}7!9+^Wl}Uk?`S$#V2%pQ*SIH5KI-mn%i;Z7-)m$mN9CnI$G7?# zo`zVrUwoSL&_dJ92YhX5TKqaRkfPgC4=Q&=K+;_aDs&OU0&{WFH}kKX6uNQC6%oUH z2DZa1s3%Vtk|bglbxep-w)PbFG!J17`<$g8lVhqD2w;Z0zGsh-r zxZ13G$G<48leNqR!DCVt9)@}(zMI5w6Wo=N zpP1*3DI;~h2WDWgcKn*f!+ORD)f$DZFwgKBafEZmeXQMAsq9sxP9A)7zOYnkHT9JU zRA`umgmP9d6=PHmFIgx=0$(sjb>+0CHG)K@cPG{IxaJ&Ueo8)0RWgV9+gO7+Bl1(F z7!BslJ2MP*PWJ;x)QXbR$6jEr5q3 z(3}F@YO_P1NyTdEXRLU6fp?9V2-S=E+YaeLL{Y)W%6`k7$(EW8EZSA*(+;e5@jgD^I zaJQ2|oCM1n!A&-8`;#RDcZyk*+RPkn_r8?Ak@agHiSp*qFNX)&i21HE?yuZ;-C<3C zwJGd1lx5UzViP7sZJ&|LqH*mryb}y|%AOw+v)yc`qM)03qyyrqhX?ub`Cjwx2PrR! z)_z>5*!*$x1=Qa-0uE7jy0z`>|Ni#X+uV|%_81F7)b+nf%iz=`fF4g5UfHS_?PHbr zB;0$bK@=di?f`dS(j{l3-tSCfp~zUuva+=EWxJcRfp(<$@vd(GigM&~vaYZ0c#BTs z3ijkxMl=vw5AS&DcXQ%eeKt!uKvh2l3W?&3=dBHU=Gz?O!40S&&~ei2vg**c$o;i89~6DVns zG>9a*`k5)NI9|?W!@9>rzJ;9EJ=YlJTx1r1BA?H`LWijk(rTax9(OAu;q4_wTj-yj z1%W4GW&K4T=uEGb+E!>W0SD_C0RR91 literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-512.png b/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-maskable-192.png b/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/example/web/icons/Icon-maskable-512.png b/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/example/web/index.html b/example/web/index.html new file mode 100644 index 0000000..41b3bc3 --- /dev/null +++ b/example/web/index.html @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + example + + + + + + + + + + diff --git a/example/web/manifest.json b/example/web/manifest.json new file mode 100644 index 0000000..096edf8 --- /dev/null +++ b/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "example", + "short_name": "example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/flutter_typeahead.gif b/flutter_typeahead.gif new file mode 100644 index 0000000000000000000000000000000000000000..ebf22bd31696c61f0c0b27b478bdc978c98a99e3 GIT binary patch literal 354997 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

kEMt7VICaI`mi>Vc5 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%0DtG$=*7@ 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

rmMWMo9t1D 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 literal 0 HcmV?d00001 diff --git a/flutter_typeahead.iml b/flutter_typeahead.iml new file mode 100644 index 0000000..70b4a9b --- /dev/null +++ b/flutter_typeahead.iml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/flutter_typeahead.dart b/lib/flutter_typeahead.dart new file mode 100644 index 0000000..d6495f7 --- /dev/null +++ b/lib/flutter_typeahead.dart @@ -0,0 +1,17 @@ +library flutter_typeahead; + +export 'package:flutter_typeahead/src/typedef.dart'; +export 'package:flutter_typeahead/src/material/field/typeahead_field.dart'; +export 'package:flutter_typeahead/src/material/field/text_field_configuration.dart'; +export 'package:flutter_typeahead/src/material/field/typeahead_form_field.dart'; +export 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_controller.dart'; +export 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_decoration.dart'; +export 'package:flutter_typeahead/src/material/suggestions_box/suggestions_list.dart'; +export 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box.dart'; +export 'package:flutter_typeahead/src/cupertino/field/cupertino_typeahead_field.dart'; +export 'package:flutter_typeahead/src/cupertino/field/cupertino_text_field_configuration.dart'; +export 'package:flutter_typeahead/src/cupertino/field/cupertino_typeahead_form_field.dart'; +export 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_list.dart'; +export 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart'; +export 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart'; +export 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box.dart'; \ No newline at end of file diff --git a/lib/src/cupertino/field/cupertino_text_field_configuration.dart b/lib/src/cupertino/field/cupertino_text_field_configuration.dart new file mode 100644 index 0000000..5602ba5 --- /dev/null +++ b/lib/src/cupertino/field/cupertino_text_field_configuration.dart @@ -0,0 +1,185 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; + +// Cupertino BoxDecoration taken from flutter/lib/src/cupertino/text_field.dart +const BorderSide _kDefaultRoundedBorderSide = BorderSide( + color: CupertinoDynamicColor.withBrightness( + color: Color(0x33000000), + darkColor: Color(0x33FFFFFF), + ), + style: BorderStyle.solid, + width: 0.0, +); + +const Border _kDefaultRoundedBorder = Border( + top: _kDefaultRoundedBorderSide, + bottom: _kDefaultRoundedBorderSide, + left: _kDefaultRoundedBorderSide, + right: _kDefaultRoundedBorderSide, +); + +const BoxDecoration _kDefaultRoundedBorderDecoration = BoxDecoration( + color: CupertinoDynamicColor.withBrightness( + color: CupertinoColors.white, + darkColor: CupertinoColors.black, + ), + border: _kDefaultRoundedBorder, + borderRadius: BorderRadius.all(Radius.circular(5.0)), +); + +/// Supply an instance of this class to the [TypeAhead.textFieldConfiguration] +/// property to configure the displayed text field. See [documentation](https://docs.flutter.io/flutter/cupertino/CupertinoTextField-class.html) +/// for more information on properties. +class CupertinoTextFieldConfiguration { + final TextEditingController? controller; + final FocusNode? focusNode; + final BoxDecoration decoration; + final EdgeInsetsGeometry padding; + final String? placeholder; + final Widget? prefix; + final OverlayVisibilityMode prefixMode; + final Widget? suffix; + final OverlayVisibilityMode suffixMode; + final OverlayVisibilityMode clearButtonMode; + final TextInputType? keyboardType; + final TextInputAction? textInputAction; + final TextCapitalization textCapitalization; + final TextStyle? style; + final TextAlign textAlign; + final bool autofocus; + final bool obscureText; + final bool autocorrect; + final int maxLines; + final int? minLines; + final int? maxLength; + final MaxLengthEnforcement? maxLengthEnforcement; + final ValueChanged? onChanged; + final VoidCallback? onEditingComplete; + final GestureTapCallback? onTap; + final ValueChanged? onSubmitted; + final List? inputFormatters; + final bool enabled; + final bool enableSuggestions; + final double cursorWidth; + final Radius cursorRadius; + final Color? cursorColor; + final Brightness? keyboardAppearance; + final EdgeInsets scrollPadding; + final bool enableInteractiveSelection; + + /// Creates a CupertinoTextFieldConfiguration + const CupertinoTextFieldConfiguration({ + this.controller, + this.focusNode, + this.decoration = _kDefaultRoundedBorderDecoration, + this.padding = const EdgeInsets.all(6.0), + this.placeholder, + this.prefix, + this.prefixMode = OverlayVisibilityMode.always, + this.suffix, + this.suffixMode = OverlayVisibilityMode.always, + this.clearButtonMode = OverlayVisibilityMode.never, + this.keyboardType, + this.textInputAction, + this.textCapitalization = TextCapitalization.none, + this.style, + this.textAlign = TextAlign.start, + this.autofocus = false, + this.obscureText = false, + this.autocorrect = true, + this.maxLines = 1, + this.minLines, + this.maxLength, + this.maxLengthEnforcement, + this.onChanged, + this.onEditingComplete, + this.onTap, + this.onSubmitted, + this.inputFormatters, + this.enabled = true, + this.enableSuggestions = true, + this.cursorWidth = 2.0, + this.cursorRadius = const Radius.circular(2.0), + this.cursorColor, + this.keyboardAppearance, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + }); + + /// Copies the [CupertinoTextFieldConfiguration] and only changes the specified properties + CupertinoTextFieldConfiguration copyWith({ + TextEditingController? controller, + FocusNode? focusNode, + BoxDecoration? decoration, + EdgeInsetsGeometry? padding, + String? placeholder, + Widget? prefix, + OverlayVisibilityMode? prefixMode, + Widget? suffix, + OverlayVisibilityMode? suffixMode, + OverlayVisibilityMode? clearButtonMode, + TextInputType? keyboardType, + TextInputAction? textInputAction, + TextCapitalization? textCapitalization, + TextStyle? style, + TextAlign? textAlign, + bool? autofocus, + bool? obscureText, + bool? autocorrect, + int? maxLines, + int? minLines, + int? maxLength, + MaxLengthEnforcement? maxLengthEnforcement, + ValueChanged? onChanged, + VoidCallback? onEditingComplete, + GestureTapCallback? onTap, + ValueChanged? onSubmitted, + List? inputFormatters, + bool? enabled, + bool? enableSuggestions, + double? cursorWidth, + Radius? cursorRadius, + Color? cursorColor, + Brightness? keyboardAppearance, + EdgeInsets? scrollPadding, + bool? enableInteractiveSelection, + }) { + return CupertinoTextFieldConfiguration( + controller: controller ?? this.controller, + focusNode: focusNode ?? this.focusNode, + decoration: decoration ?? this.decoration, + padding: padding ?? this.padding, + placeholder: placeholder ?? this.placeholder, + prefix: prefix ?? this.prefix, + prefixMode: prefixMode ?? this.prefixMode, + suffix: suffix ?? this.suffix, + suffixMode: suffixMode ?? this.suffixMode, + clearButtonMode: clearButtonMode ?? this.clearButtonMode, + keyboardType: keyboardType ?? this.keyboardType, + textInputAction: textInputAction ?? this.textInputAction, + textCapitalization: textCapitalization ?? this.textCapitalization, + style: style ?? this.style, + textAlign: textAlign ?? this.textAlign, + autofocus: autofocus ?? this.autofocus, + obscureText: obscureText ?? this.obscureText, + autocorrect: autocorrect ?? this.autocorrect, + maxLines: maxLines ?? this.maxLines, + minLines: minLines ?? this.minLines, + maxLength: maxLength ?? this.maxLength, + maxLengthEnforcement: maxLengthEnforcement ?? this.maxLengthEnforcement, + onChanged: onChanged ?? this.onChanged, + onEditingComplete: onEditingComplete ?? this.onEditingComplete, + onTap: onTap ?? this.onTap, + onSubmitted: onSubmitted ?? this.onSubmitted, + inputFormatters: inputFormatters ?? this.inputFormatters, + enabled: enabled ?? this.enabled, + enableSuggestions: enableSuggestions ?? this.enableSuggestions, + cursorWidth: cursorWidth ?? this.cursorWidth, + cursorRadius: cursorRadius ?? this.cursorRadius, + cursorColor: cursorColor ?? this.cursorColor, + keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance, + scrollPadding: scrollPadding ?? this.scrollPadding, + enableInteractiveSelection: enableInteractiveSelection ?? this.enableInteractiveSelection, + ); + } +} diff --git a/lib/src/cupertino/field/cupertino_typeahead_field.dart b/lib/src/cupertino/field/cupertino_typeahead_field.dart new file mode 100644 index 0000000..1707bc4 --- /dev/null +++ b/lib/src/cupertino/field/cupertino_typeahead_field.dart @@ -0,0 +1,560 @@ +import 'dart:async'; +import 'dart:core'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:flutter_typeahead/src/cupertino/field/cupertino_text_field_configuration.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_list.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; +import 'package:flutter_typeahead/src/utils.dart'; + +/// A [CupertinoTextField](https://docs.flutter.io/flutter/cupertino/CupertinoTextField-class.html) +/// that displays a list of suggestions as the user types +/// +/// See also: +/// +/// * [TypeAheadFormField], a [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +/// implementation of [TypeAheadField] that allows the value to be saved, +/// validated, etc. +class CupertinoTypeAheadField extends StatefulWidget { + /// Called with the search pattern to get the search suggestions. + /// + /// This callback must not be null. It is be called by the TypeAhead widget + /// and provided with the search pattern. It should return a [List](https://api.dartlang.org/stable/2.0.0/dart-core/List-class.html) + /// of suggestions either synchronously, or asynchronously (as the result of a + /// [Future](https://api.dartlang.org/stable/dart-async/Future-class.html)). + /// Typically, the list of suggestions should not contain more than 4 or 5 + /// entries. These entries will then be provided to [itemBuilder] to display + /// the suggestions. + /// + /// Example: + /// ```dart + /// suggestionsCallback: (pattern) async { + /// return await _getSuggestions(pattern); + /// } + /// ``` + final SuggestionsCallback suggestionsCallback; + + /// Called when a suggestion is tapped. + /// + /// This callback must not be null. It is called by the TypeAhead widget and + /// provided with the value of the tapped suggestion. + /// + /// For example, you might want to navigate to a specific view when the user + /// tabs a suggestion: + /// ```dart + /// onSuggestionSelected: (suggestion) { + /// Navigator.of(context).push(MaterialPageRoute( + /// builder: (context) => SearchResult( + /// searchItem: suggestion + /// ) + /// )); + /// } + /// ``` + /// + /// Or to set the value of the text field: + /// ```dart + /// onSuggestionSelected: (suggestion) { + /// _controller.text = suggestion['name']; + /// } + /// ``` + final SuggestionSelectionCallback onSuggestionSelected; + + /// Called for each suggestion returned by [suggestionsCallback] to build the + /// corresponding widget. + /// + /// This callback must not be null. It is called by the TypeAhead widget for + /// each suggestion, and expected to build a widget to display this + /// suggestion's info. For example: + /// + /// ```dart + /// itemBuilder: (context, suggestion) { + /// return Padding( + /// padding: const EdgeInsets.all(4.0), + /// child: Text( + /// suggestion, + /// ), + /// ); + /// } + /// ``` + final ItemBuilder itemBuilder; + + /// The decoration of the material sheet that contains the suggestions. + final CupertinoSuggestionsBoxDecoration suggestionsBoxDecoration; + + /// Used to control the `_SuggestionsBox`. Allows manual control to + /// open, close, toggle, or resize the `_SuggestionsBox`. + final CupertinoSuggestionsBoxController? suggestionsBoxController; + + /// The duration to wait after the user stops typing before calling + /// [suggestionsCallback] + /// + /// This is useful, because, if not set, a request for suggestions will be + /// sent for every character that the user types. + /// + /// This duration is set by default to 300 milliseconds + final Duration debounceDuration; + + /// Called when waiting for [suggestionsCallback] to return. + /// + /// It is expected to return a widget to display while waiting. + /// For example: + /// ```dart + /// (BuildContext context) { + /// return Text('Loading...'); + /// } + /// ``` + /// + /// If not specified, a [CupertinoActivityIndicator](https://docs.flutter.io/flutter/cupertino/CupertinoActivityIndicator-class.html) is shown + final WidgetBuilder? loadingBuilder; + + /// Called when [suggestionsCallback] returns an empty array. + /// + /// It is expected to return a widget to display when no suggestions are + /// avaiable. + /// For example: + /// ```dart + /// (BuildContext context) { + /// return Text('No Items Found!'); + /// } + /// ``` + /// + /// If not specified, a simple text is shown + final WidgetBuilder? noItemsFoundBuilder; + + /// Called when [suggestionsCallback] throws an exception. + /// + /// It is called with the error object, and expected to return a widget to + /// display when an exception is thrown + /// For example: + /// ```dart + /// (BuildContext context, error) { + /// return Text('$error'); + /// } + /// ``` + final ErrorBuilder? errorBuilder; + + /// Called to display animations when [suggestionsCallback] returns suggestions + /// + /// It is provided with the suggestions box instance and the animation + /// controller, and expected to return some animation that uses the controller + /// to display the suggestion box. + /// + /// For example: + /// ```dart + /// transitionBuilder: (context, suggestionsBox, animationController) { + /// return FadeTransition( + /// child: suggestionsBox, + /// opacity: CurvedAnimation( + /// parent: animationController, + /// curve: Curves.fastOutSlowIn + /// ), + /// ); + /// } + /// ``` + /// This argument is best used with [animationDuration] and [animationStart] + /// to fully control the animation. + /// + /// To fully remove the animation, just return `suggestionsBox` + /// + /// If not specified, a [SizeTransition](https://docs.flutter.io/flutter/widgets/SizeTransition-class.html) is shown. + final AnimationTransitionBuilder? transitionBuilder; + + /// The duration that [transitionBuilder] animation takes. + /// + /// This argument is best used with [transitionBuilder] and [animationStart] + /// to fully control the animation. + /// + /// Defaults to 500 milliseconds. + final Duration animationDuration; + + /// Determine the [SuggestionBox]'s direction. + /// + /// If [AxisDirection.down], the [SuggestionBox] will be below the [TextField] + /// and the [_SuggestionsList] will grow **down**. + /// + /// If [AxisDirection.up], the [SuggestionBox] will be above the [TextField] + /// and the [_SuggestionsList] will grow **up**. + /// + /// [AxisDirection.left] and [AxisDirection.right] are not allowed. + final AxisDirection direction; + + /// The value at which the [transitionBuilder] animation starts. + /// + /// This argument is best used with [transitionBuilder] and [animationDuration] + /// to fully control the animation. + /// + /// Defaults to 0.25. + final double animationStart; + + /// The configuration of the [CupertinoTextField](https://docs.flutter.io/flutter/cupertino/CupertinoTextField-class.html) + /// that the TypeAhead widget displays + final CupertinoTextFieldConfiguration textFieldConfiguration; + + /// How far below the text field should the suggestions box be + /// + /// Defaults to 5.0 + final double suggestionsBoxVerticalOffset; + + /// If set to true, suggestions will be fetched immediately when the field is + /// added to the view. + /// + /// But the suggestions box will only be shown when the field receives focus. + /// To make the field receive focus immediately, you can set the `autofocus` + /// property in the [textFieldConfiguration] to true + /// + /// Defaults to false + final bool getImmediateSuggestions; + + /// If set to true, no loading box will be shown while suggestions are + /// being fetched. [loadingBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnLoading; + + /// If set to true, nothing will be shown if there are no results. + /// [noItemsFoundBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnEmpty; + + /// If set to true, nothing will be shown if there is an error. + /// [errorBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnError; + + /// If set to false, the suggestions box will stay opened after + /// the keyboard is closed. + /// + /// Defaults to true. + final bool hideSuggestionsOnKeyboardHide; + + /// If set to false, the suggestions box will show a circular + /// progress indicator when retrieving suggestions. + /// + /// Defaults to true. + final bool keepSuggestionsOnLoading; + + /// If set to true, the suggestions box will remain opened even after + /// selecting a suggestion. + /// + /// Note that if this is enabled, the only way + /// to close the suggestions box is either manually via the + /// `SuggestionsBoxController` or when the user closes the software + /// keyboard if `hideSuggestionsOnKeyboardHide` is set to true. Users + /// with a physical keyboard will be unable to close the + /// box without a manual way via `SuggestionsBoxController`. + /// + /// Defaults to false. + final bool keepSuggestionsOnSuggestionSelected; + + /// If set to true, in the case where the suggestions box has less than + /// _SuggestionsBoxController.minOverlaySpace to grow in the desired [direction], the direction axis + /// will be temporarily flipped if there's more room available in the opposite + /// direction. + /// + /// Defaults to false + final bool autoFlipDirection; + + /// If set to false, suggestion list will not be reversed according to the + /// [autoFlipDirection] property. + /// + /// Defaults to true. + final bool autoFlipListDirection; + + /// The minimum number of characters which must be entered before + /// [suggestionsCallback] is triggered. + /// + /// Defaults to 0. + final int minCharsForSuggestions; + + /// If set to true and if the user scrolls through the suggestion list, hide the keyboard automatically. + /// If set to false, the keyboard remains visible. + /// Throws an exception, if hideKeyboardOnDrag and hideSuggestionsOnKeyboardHide are both set to true as + /// they are mutual exclusive. + /// + /// Defaults to false + final bool hideKeyboardOnDrag; + + /// Creates a [CupertinoTypeAheadField] + CupertinoTypeAheadField({ + Key? key, + required this.suggestionsCallback, + required this.itemBuilder, + required this.onSuggestionSelected, + this.textFieldConfiguration = const CupertinoTextFieldConfiguration(), + this.suggestionsBoxDecoration = const CupertinoSuggestionsBoxDecoration(), + this.debounceDuration = const Duration(milliseconds: 300), + this.suggestionsBoxController, + this.loadingBuilder, + this.noItemsFoundBuilder, + this.errorBuilder, + this.transitionBuilder, + this.animationStart = 0.25, + this.animationDuration = const Duration(milliseconds: 500), + this.getImmediateSuggestions = false, + this.suggestionsBoxVerticalOffset = 5.0, + this.direction = AxisDirection.down, + this.hideOnLoading = false, + this.hideOnEmpty = false, + this.hideOnError = false, + this.hideSuggestionsOnKeyboardHide = true, + this.keepSuggestionsOnLoading = true, + this.keepSuggestionsOnSuggestionSelected = false, + this.autoFlipDirection = false, + this.autoFlipListDirection = true, + this.minCharsForSuggestions = 0, + this.hideKeyboardOnDrag = true, + }) : assert(animationStart >= 0.0 && animationStart <= 1.0), + assert(direction == AxisDirection.down || direction == AxisDirection.up), + assert(minCharsForSuggestions >= 0), + assert(!hideKeyboardOnDrag || hideKeyboardOnDrag && !hideSuggestionsOnKeyboardHide), + super(key: key); + + @override + _CupertinoTypeAheadFieldState createState() => _CupertinoTypeAheadFieldState(); +} + +class _CupertinoTypeAheadFieldState extends State> with WidgetsBindingObserver { + FocusNode? _focusNode; + TextEditingController? _textEditingController; + CupertinoSuggestionsBox? _suggestionsBox; + + TextEditingController? get _effectiveController => widget.textFieldConfiguration.controller ?? _textEditingController; + + FocusNode? get _effectiveFocusNode => widget.textFieldConfiguration.focusNode ?? _focusNode; + late VoidCallback _focusNodeListener; + + final LayerLink _layerLink = LayerLink(); + + // Timer that resizes the suggestion box on each tick. Only active when the user is scrolling. + Timer? _resizeOnScrollTimer; + + // The rate at which the suggestion box will resize when the user is scrolling + final Duration _resizeOnScrollRefreshRate = const Duration(milliseconds: 500); + + // Will have a value if the typeahead is inside a scrollable widget + ScrollPosition? _scrollPosition; + + // Keyboard detection + final Stream? _keyboardVisibility = (supportedPlatform) ? KeyboardVisibilityController().onChange : null; + late StreamSubscription? _keyboardVisibilitySubscription; + + @override + void didChangeMetrics() { + // Catch keyboard event and orientation change; resize suggestions list + this._suggestionsBox!.onChangeMetrics(); + } + + @override + void dispose() { + this._suggestionsBox!.close(); + this._suggestionsBox!.widgetMounted = false; + WidgetsBinding.instance.removeObserver(this); + _keyboardVisibilitySubscription?.cancel(); + _effectiveFocusNode!.removeListener(_focusNodeListener); + _focusNode?.dispose(); + _resizeOnScrollTimer?.cancel(); + _scrollPosition?.removeListener(_scrollResizeListener); + _textEditingController?.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + + if (widget.textFieldConfiguration.controller == null) { + this._textEditingController = TextEditingController(); + } + + if (widget.textFieldConfiguration.focusNode == null) { + this._focusNode = FocusNode(); + } + + this._suggestionsBox = CupertinoSuggestionsBox( + context, + widget.direction, + widget.autoFlipDirection, + widget.autoFlipListDirection, + ); + + widget.suggestionsBoxController?.suggestionsBox = this._suggestionsBox; + widget.suggestionsBoxController?.effectiveFocusNode = this._effectiveFocusNode; + + this._focusNodeListener = () { + if (_effectiveFocusNode!.hasFocus) { + this._suggestionsBox!.open(); + } else { + this._suggestionsBox!.close(); + } + }; + + this._effectiveFocusNode!.addListener(_focusNodeListener); + + // hide suggestions box on keyboard closed + this._keyboardVisibilitySubscription = _keyboardVisibility?.listen((bool isVisible) { + if (widget.hideSuggestionsOnKeyboardHide && !isVisible) { + _effectiveFocusNode!.unfocus(); + } + }); + + WidgetsBinding.instance.addPostFrameCallback((duration) { + if (mounted) { + this._initOverlayEntry(); + // calculate initial suggestions list size + this._suggestionsBox!.resize(); + + // in case we already missed the focus event + if (this._effectiveFocusNode!.hasFocus) { + this._suggestionsBox!.open(); + } + } + }); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final scrollableState = Scrollable.maybeOf(context); + if (scrollableState != null) { + // The TypeAheadField is inside a scrollable widget + _scrollPosition = scrollableState.position; + + _scrollPosition!.removeListener(_scrollResizeListener); + _scrollPosition!.isScrollingNotifier.addListener(_scrollResizeListener); + } + } + + void _scrollResizeListener() { + bool isScrolling = _scrollPosition!.isScrollingNotifier.value; + _resizeOnScrollTimer?.cancel(); + if (isScrolling) { + // Scroll started + _resizeOnScrollTimer = Timer.periodic(_resizeOnScrollRefreshRate, (timer) { + _suggestionsBox!.resize(); + }); + } else { + // Scroll finished + _suggestionsBox!.resize(); + } + } + + void _initOverlayEntry() { + this._suggestionsBox!.overlayEntry = OverlayEntry(builder: (context) { + final suggestionsList = CupertinoSuggestionsList( + suggestionsBox: _suggestionsBox, + decoration: widget.suggestionsBoxDecoration, + debounceDuration: widget.debounceDuration, + controller: this._effectiveController, + loadingBuilder: widget.loadingBuilder, + noItemsFoundBuilder: widget.noItemsFoundBuilder, + errorBuilder: widget.errorBuilder, + transitionBuilder: widget.transitionBuilder, + suggestionsCallback: widget.suggestionsCallback, + animationDuration: widget.animationDuration, + animationStart: widget.animationStart, + getImmediateSuggestions: widget.getImmediateSuggestions, + onSuggestionSelected: (T selection) { + if (!widget.keepSuggestionsOnSuggestionSelected) { + this._effectiveFocusNode!.unfocus(); + this._suggestionsBox!.close(); + } + widget.onSuggestionSelected(selection); + }, + itemBuilder: widget.itemBuilder, + direction: _suggestionsBox!.direction, + hideOnLoading: widget.hideOnLoading, + hideOnEmpty: widget.hideOnEmpty, + hideOnError: widget.hideOnError, + keepSuggestionsOnLoading: widget.keepSuggestionsOnLoading, + minCharsForSuggestions: widget.minCharsForSuggestions, + hideKeyboardOnDrag: widget.hideKeyboardOnDrag, + ); + + double w = _suggestionsBox!.textBoxWidth; + if (widget.suggestionsBoxDecoration.constraints != null) { + if (widget.suggestionsBoxDecoration.constraints!.minWidth != 0.0 && + widget.suggestionsBoxDecoration.constraints!.maxWidth != double.infinity) { + w = (widget.suggestionsBoxDecoration.constraints!.minWidth + + widget.suggestionsBoxDecoration.constraints!.maxWidth) / + 2; + } else if (widget.suggestionsBoxDecoration.constraints!.minWidth != 0.0 && + widget.suggestionsBoxDecoration.constraints!.minWidth > w) { + w = widget.suggestionsBoxDecoration.constraints!.minWidth; + } else if (widget.suggestionsBoxDecoration.constraints!.maxWidth != double.infinity && + widget.suggestionsBoxDecoration.constraints!.maxWidth < w) { + w = widget.suggestionsBoxDecoration.constraints!.maxWidth; + } + } + + return Positioned( + width: w, + child: CompositedTransformFollower( + link: this._layerLink, + showWhenUnlinked: false, + offset: Offset( + widget.suggestionsBoxDecoration.offsetX, + _suggestionsBox!.direction == AxisDirection.down + ? _suggestionsBox!.textBoxHeight + widget.suggestionsBoxVerticalOffset + : _suggestionsBox!.directionUpOffset), + child: _suggestionsBox!.direction == AxisDirection.down + ? suggestionsList + : FractionalTranslation( + translation: Offset(0.0, -1.0), // visually flips list to go up + child: suggestionsList, + ), + ), + ); + }); + } + + @override + Widget build(BuildContext context) { + return CompositedTransformTarget( + link: this._layerLink, + child: CupertinoTextField( + controller: this._effectiveController, + focusNode: this._effectiveFocusNode, + decoration: widget.textFieldConfiguration.decoration, + padding: widget.textFieldConfiguration.padding, + placeholder: widget.textFieldConfiguration.placeholder, + prefix: widget.textFieldConfiguration.prefix, + prefixMode: widget.textFieldConfiguration.prefixMode, + suffix: widget.textFieldConfiguration.suffix, + suffixMode: widget.textFieldConfiguration.suffixMode, + clearButtonMode: widget.textFieldConfiguration.clearButtonMode, + keyboardType: widget.textFieldConfiguration.keyboardType, + textInputAction: widget.textFieldConfiguration.textInputAction, + textCapitalization: widget.textFieldConfiguration.textCapitalization, + style: widget.textFieldConfiguration.style, + textAlign: widget.textFieldConfiguration.textAlign, + autofocus: widget.textFieldConfiguration.autofocus, + obscureText: widget.textFieldConfiguration.obscureText, + autocorrect: widget.textFieldConfiguration.autocorrect, + maxLines: widget.textFieldConfiguration.maxLines, + minLines: widget.textFieldConfiguration.minLines, + maxLength: widget.textFieldConfiguration.maxLength, + maxLengthEnforcement: widget.textFieldConfiguration.maxLengthEnforcement, + onChanged: widget.textFieldConfiguration.onChanged, + onEditingComplete: widget.textFieldConfiguration.onEditingComplete, + onTap: widget.textFieldConfiguration.onTap, +// onTapOutside: (_){}, + onSubmitted: widget.textFieldConfiguration.onSubmitted, + inputFormatters: widget.textFieldConfiguration.inputFormatters, + enabled: widget.textFieldConfiguration.enabled, + cursorWidth: widget.textFieldConfiguration.cursorWidth, + cursorRadius: widget.textFieldConfiguration.cursorRadius, + cursorColor: widget.textFieldConfiguration.cursorColor, + keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance, + scrollPadding: widget.textFieldConfiguration.scrollPadding, + enableInteractiveSelection: widget.textFieldConfiguration.enableInteractiveSelection, + ), + ); + } +} diff --git a/lib/src/cupertino/field/cupertino_typeahead_form_field.dart b/lib/src/cupertino/field/cupertino_typeahead_form_field.dart new file mode 100644 index 0000000..d0ac929 --- /dev/null +++ b/lib/src/cupertino/field/cupertino_typeahead_form_field.dart @@ -0,0 +1,190 @@ +import 'dart:core'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_typeahead/src/cupertino/field/cupertino_text_field_configuration.dart'; +import 'package:flutter_typeahead/src/cupertino/field/cupertino_typeahead_field.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; + + +/// A [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +/// implementation of [TypeAheadField], that allows the value to be saved, +/// validated, etc. +/// +/// See also: +/// +/// * [TypeAheadField], A [CupertinoTextField](https://docs.flutter.io/flutter/cupertino/CupertinoTextField-class.html) +/// that displays a list of suggestions as the user types +class CupertinoTypeAheadFormField extends FormField { + /// The configuration of the [CupertinoTextField](https://docs.flutter.io/flutter/cupertino/CupertinoTextField-class.html) + /// that the TypeAhead widget displays + final CupertinoTextFieldConfiguration textFieldConfiguration; + + /// Creates a [CupertinoTypeAheadFormField] + CupertinoTypeAheadFormField( + {Key? key, + String? initialValue, + bool getImmediateSuggestions = false, + @Deprecated('Use autoValidateMode parameter which provides more specific ' + 'behavior related to auto validation. ' + 'This feature was deprecated after Flutter v1.19.0.') + bool autovalidate = false, + bool enabled = true, + AutovalidateMode? autovalidateMode, + FormFieldSetter? onSaved, + FormFieldValidator? validator, + ErrorBuilder? errorBuilder, + WidgetBuilder? noItemsFoundBuilder, + WidgetBuilder? loadingBuilder, + Duration debounceDuration = const Duration(milliseconds: 300), + CupertinoSuggestionsBoxDecoration suggestionsBoxDecoration = + const CupertinoSuggestionsBoxDecoration(), + CupertinoSuggestionsBoxController? suggestionsBoxController, + required SuggestionSelectionCallback onSuggestionSelected, + required ItemBuilder itemBuilder, + required SuggestionsCallback suggestionsCallback, + double suggestionsBoxVerticalOffset = 5.0, + this.textFieldConfiguration = const CupertinoTextFieldConfiguration(), + AnimationTransitionBuilder? transitionBuilder, + Duration animationDuration = const Duration(milliseconds: 500), + double animationStart = 0.25, + AxisDirection direction = AxisDirection.down, + bool hideOnLoading = false, + bool hideOnEmpty = false, + bool hideOnError = false, + bool hideSuggestionsOnKeyboardHide = true, + bool keepSuggestionsOnLoading = true, + bool keepSuggestionsOnSuggestionSelected = false, + bool autoFlipDirection = false, + bool autoFlipListDirection = true, + int minCharsForSuggestions = 0, + bool hideKeyboardOnDrag = false}) + : assert( + initialValue == null || textFieldConfiguration.controller == null), + assert(minCharsForSuggestions >= 0), + super( + key: key, + onSaved: onSaved, + validator: validator, + initialValue: textFieldConfiguration.controller != null + ? textFieldConfiguration.controller!.text + : (initialValue ?? ''), + enabled: enabled, + autovalidateMode: autovalidateMode, + builder: (FormFieldState field) { + final CupertinoTypeAheadFormFieldState state = + field as CupertinoTypeAheadFormFieldState; + + return CupertinoTypeAheadField( + getImmediateSuggestions: getImmediateSuggestions, + transitionBuilder: transitionBuilder, + errorBuilder: errorBuilder, + noItemsFoundBuilder: noItemsFoundBuilder, + loadingBuilder: loadingBuilder, + debounceDuration: debounceDuration, + suggestionsBoxDecoration: suggestionsBoxDecoration, + suggestionsBoxController: suggestionsBoxController, + textFieldConfiguration: textFieldConfiguration.copyWith( + onChanged: (text) { + state.didChange(text); + textFieldConfiguration.onChanged?.call(text); + }, + controller: state._effectiveController, + ), + suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, + onSuggestionSelected: onSuggestionSelected, + itemBuilder: itemBuilder, + suggestionsCallback: suggestionsCallback, + animationStart: animationStart, + animationDuration: animationDuration, + direction: direction, + hideOnLoading: hideOnLoading, + hideOnEmpty: hideOnEmpty, + hideOnError: hideOnError, + hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, + keepSuggestionsOnLoading: keepSuggestionsOnLoading, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, + autoFlipDirection: autoFlipDirection, + autoFlipListDirection: autoFlipListDirection, + minCharsForSuggestions: minCharsForSuggestions, + hideKeyboardOnDrag: hideKeyboardOnDrag, + ); + }); + + @override + CupertinoTypeAheadFormFieldState createState() => + CupertinoTypeAheadFormFieldState(); +} + +class CupertinoTypeAheadFormFieldState extends FormFieldState { + TextEditingController? _controller; + + TextEditingController? get _effectiveController => + widget.textFieldConfiguration.controller ?? _controller; + + @override + CupertinoTypeAheadFormField get widget => + super.widget as CupertinoTypeAheadFormField; + + @override + void initState() { + super.initState(); + if (widget.textFieldConfiguration.controller == null) { + _controller = TextEditingController(text: widget.initialValue); + } else { + widget.textFieldConfiguration.controller! + .addListener(_handleControllerChanged); + } + } + + @override + void didUpdateWidget(CupertinoTypeAheadFormField oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.textFieldConfiguration.controller != + oldWidget.textFieldConfiguration.controller) { + oldWidget.textFieldConfiguration.controller + ?.removeListener(_handleControllerChanged); + widget.textFieldConfiguration.controller + ?.addListener(_handleControllerChanged); + + if (oldWidget.textFieldConfiguration.controller != null && + widget.textFieldConfiguration.controller == null) + _controller = TextEditingController.fromValue( + oldWidget.textFieldConfiguration.controller!.value); + if (widget.textFieldConfiguration.controller != null) { + setValue(widget.textFieldConfiguration.controller!.text); + if (oldWidget.textFieldConfiguration.controller == null) + _controller = null; + } + } + } + + @override + void dispose() { + widget.textFieldConfiguration.controller + ?.removeListener(_handleControllerChanged); + super.dispose(); + } + + @override + void reset() { + super.reset(); + setState(() { + _effectiveController!.text = widget.initialValue!; + }); + } + + void _handleControllerChanged() { + // Suppress changes that originated from within this class. + // + // In the case where a controller has been passed in to this widget, we + // register this change listener. In these cases, we'll also receive change + // notifications for changes originating from within this class -- for + // example, the reset() method. In such cases, the FormField value will + // already have been set. + if (_effectiveController!.text != value) + didChange(_effectiveController!.text); + } +} \ No newline at end of file diff --git a/lib/src/cupertino/suggestions_box/cupertino_suggestions_box.dart b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box.dart new file mode 100644 index 0000000..0ca2ce7 --- /dev/null +++ b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box.dart @@ -0,0 +1,212 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_typeahead/src/cupertino/field/cupertino_typeahead_field.dart'; + +class CupertinoSuggestionsBox { + static const int waitMetricsTimeoutMillis = 1000; + static const double minOverlaySpace = 64.0; + + final BuildContext context; + final AxisDirection desiredDirection; + final bool autoFlipDirection; + final bool autoFlipListDirection; + + OverlayEntry? overlayEntry; + AxisDirection direction; + + bool isOpened = false; + bool widgetMounted = true; + double maxHeight = 300.0; + double textBoxWidth = 100.0; + double textBoxHeight = 100.0; + late double directionUpOffset; + + CupertinoSuggestionsBox( + this.context, + this.direction, + this.autoFlipDirection, + this.autoFlipListDirection, + ) : desiredDirection = direction; + + void open() { + if (this.isOpened) return; + assert(this.overlayEntry != null); + resize(); + Overlay.of(context).insert(this.overlayEntry!); + this.isOpened = true; + } + + void close() { + if (!this.isOpened) return; + assert(this.overlayEntry != null); + this.overlayEntry!.remove(); + this.isOpened = false; + } + + void toggle() { + if (this.isOpened) { + this.close(); + } else { + this.open(); + } + } + + MediaQuery? _findRootMediaQuery() { + MediaQuery? rootMediaQuery; + context.visitAncestorElements((element) { + if (element.widget is MediaQuery) { + rootMediaQuery = element.widget as MediaQuery; + } + return true; + }); + + return rootMediaQuery; + } + + /// Delays until the keyboard has toggled or the orientation has fully changed + Future _waitChangeMetrics() async { + if (widgetMounted) { + // initial viewInsets which are before the keyboard is toggled + EdgeInsets initial = MediaQuery.of(context).viewInsets; + // initial MediaQuery for orientation change + MediaQuery? initialRootMediaQuery = _findRootMediaQuery(); + + int timer = 0; + // viewInsets or MediaQuery have changed once keyboard has toggled or orientation has changed + while (widgetMounted && timer < waitMetricsTimeoutMillis) { + // TODO: reduce delay if showDialog ever exposes detection of animation end + await Future.delayed(const Duration(milliseconds: 170)); + timer += 170; + + if (widgetMounted && + (MediaQuery.of(context).viewInsets != initial || + _findRootMediaQuery() != initialRootMediaQuery)) { + return true; + } + } + } + + return false; + } + + void resize() { + // check to see if widget is still mounted + // user may have closed the widget with the keyboard still open + if (widgetMounted) { + _adjustMaxHeightAndOrientation(); + overlayEntry!.markNeedsBuild(); + } + } + + // See if there's enough room in the desired direction for the overlay to display + // correctly. If not, try the opposite direction if things look more roomy there + void _adjustMaxHeightAndOrientation() { + CupertinoTypeAheadField widget = context.widget as CupertinoTypeAheadField; + + RenderBox box = context.findRenderObject() as RenderBox; + textBoxWidth = box.size.width; + textBoxHeight = box.size.height; + + // top of text box + double textBoxAbsY = box.localToGlobal(Offset.zero).dy; + + // height of window + double windowHeight = MediaQuery.of(context).size.height; + + // we need to find the root MediaQuery for the unsafe area height + // we cannot use BuildContext.ancestorWidgetOfExactType because + // widgets like SafeArea creates a new MediaQuery with the padding removed + MediaQuery rootMediaQuery = _findRootMediaQuery()!; + + // height of keyboard + double keyboardHeight = rootMediaQuery.data.viewInsets.bottom; + + double maxHDesired = _calculateMaxHeight(desiredDirection, box, widget, + windowHeight, rootMediaQuery, keyboardHeight, textBoxAbsY); + + // if there's enough room in the desired direction, update the direction and the max height + if (maxHDesired >= minOverlaySpace || !autoFlipDirection) { + direction = desiredDirection; + maxHeight = maxHDesired; + } else { + // There's not enough room in the desired direction so see how much room is in the opposite direction + AxisDirection flipped = flipAxisDirection(desiredDirection); + double maxHFlipped = _calculateMaxHeight(flipped, box, widget, + windowHeight, rootMediaQuery, keyboardHeight, textBoxAbsY); + + // if there's more room in this opposite direction, update the direction and maxHeight + if (maxHFlipped > maxHDesired) { + direction = flipped; + maxHeight = maxHFlipped; + } + } + + if (maxHeight < 0) maxHeight = 0; + } + + double _calculateMaxHeight( + AxisDirection direction, + RenderBox box, + CupertinoTypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + return direction == AxisDirection.down + ? _calculateMaxHeightDown(box, widget, windowHeight, rootMediaQuery, + keyboardHeight, textBoxAbsY) + : _calculateMaxHeightUp(box, widget, windowHeight, rootMediaQuery, + keyboardHeight, textBoxAbsY); + } + + double _calculateMaxHeightDown( + RenderBox box, + CupertinoTypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + // unsafe area, ie: iPhone X 'home button' + // keyboardHeight includes unsafeAreaHeight, if keyboard is showing, set to 0 + double unsafeAreaHeight = + keyboardHeight == 0 ? rootMediaQuery.data.padding.bottom : 0; + + return windowHeight - + keyboardHeight - + unsafeAreaHeight - + textBoxHeight - + textBoxAbsY - + 2 * widget.suggestionsBoxVerticalOffset; + } + + double _calculateMaxHeightUp( + RenderBox box, + CupertinoTypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + // recalculate keyboard absolute y value + double keyboardAbsY = windowHeight - keyboardHeight; + + directionUpOffset = textBoxAbsY > keyboardAbsY + ? keyboardAbsY - textBoxAbsY - widget.suggestionsBoxVerticalOffset + : -widget.suggestionsBoxVerticalOffset; + + // unsafe area, ie: iPhone X notch + double unsafeAreaHeight = rootMediaQuery.data.padding.top; + + return textBoxAbsY > keyboardAbsY + ? keyboardAbsY - + unsafeAreaHeight - + 2 * widget.suggestionsBoxVerticalOffset + : textBoxAbsY - + unsafeAreaHeight - + 2 * widget.suggestionsBoxVerticalOffset; + } + + Future onChangeMetrics() async { + if (await _waitChangeMetrics()) { + resize(); + } + } +} \ No newline at end of file diff --git a/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart new file mode 100644 index 0000000..07ce7d5 --- /dev/null +++ b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_controller.dart @@ -0,0 +1,33 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box.dart'; + +/// Supply an instance of this class to the [TypeAhead.suggestionsBoxController] +/// property to manually control the suggestions box +class CupertinoSuggestionsBoxController { + CupertinoSuggestionsBox? suggestionsBox; + FocusNode? effectiveFocusNode; + + /// Opens the suggestions box + void open() { + effectiveFocusNode!.requestFocus(); + } + + /// Closes the suggestions box + void close() { + effectiveFocusNode!.unfocus(); + } + + /// Opens the suggestions box if closed and vice-versa + void toggle() { + if (suggestionsBox!.isOpened) { + close(); + } else { + open(); + } + } + + /// Recalculates the height of the suggestions box + void resize() { + suggestionsBox!.resize(); + } +} \ No newline at end of file diff --git a/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart new file mode 100644 index 0000000..9c0f223 --- /dev/null +++ b/lib/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart @@ -0,0 +1,26 @@ +import 'package:flutter/cupertino.dart'; + +/// Supply an instance of this class to the [TypeAhead.suggestionsBoxDecoration] +/// property to configure the suggestions box decoration +class CupertinoSuggestionsBoxDecoration { + /// Defines if a scrollbar will be displayed or not. + final bool hasScrollbar; + + /// The constraints to be applied to the suggestions box + final BoxConstraints? constraints; + final Color? color; + final BoxBorder? border; + final BorderRadiusGeometry? borderRadius; + + /// Adds an offset to the suggestions box + final double offsetX; + + /// Creates a [CupertinoSuggestionsBoxDecoration] + const CupertinoSuggestionsBoxDecoration( + {this.hasScrollbar = true, + this.constraints, + this.color, + this.border, + this.borderRadius, + this.offsetX = 0.0}); +} \ No newline at end of file diff --git a/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart b/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart new file mode 100644 index 0000000..c3fc96a --- /dev/null +++ b/lib/src/cupertino/suggestions_box/cupertino_suggestions_list.dart @@ -0,0 +1,376 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box.dart'; +import 'package:flutter_typeahead/src/cupertino/suggestions_box/cupertino_suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; + +class CupertinoSuggestionsList extends StatefulWidget { + final CupertinoSuggestionsBox? suggestionsBox; + final TextEditingController? controller; + final bool getImmediateSuggestions; + final SuggestionSelectionCallback? onSuggestionSelected; + final SuggestionsCallback? suggestionsCallback; + final ItemBuilder? itemBuilder; + final CupertinoSuggestionsBoxDecoration? decoration; + final Duration? debounceDuration; + final WidgetBuilder? loadingBuilder; + final WidgetBuilder? noItemsFoundBuilder; + final ErrorBuilder? errorBuilder; + final AnimationTransitionBuilder? transitionBuilder; + final Duration? animationDuration; + final double? animationStart; + final AxisDirection? direction; + final bool? hideOnLoading; + final bool? hideOnEmpty; + final bool? hideOnError; + final bool? keepSuggestionsOnLoading; + final int? minCharsForSuggestions; + final bool hideKeyboardOnDrag; + + CupertinoSuggestionsList({ + required this.suggestionsBox, + this.controller, + this.getImmediateSuggestions = false, + this.onSuggestionSelected, + this.suggestionsCallback, + this.itemBuilder, + this.decoration, + this.debounceDuration, + this.loadingBuilder, + this.noItemsFoundBuilder, + this.errorBuilder, + this.transitionBuilder, + this.animationDuration, + this.animationStart, + this.direction, + this.hideOnLoading, + this.hideOnEmpty, + this.hideOnError, + this.keepSuggestionsOnLoading, + this.minCharsForSuggestions, + this.hideKeyboardOnDrag = false, + }); + + @override + _CupertinoSuggestionsListState createState() => _CupertinoSuggestionsListState(); +} + +class _CupertinoSuggestionsListState extends State> + with SingleTickerProviderStateMixin { + Iterable? _suggestions; + late bool _suggestionsValid; + late VoidCallback _controllerListener; + Timer? _debounceTimer; + bool? _isLoading, _isQueued; + Object? _error; + AnimationController? _animationController; + String? _lastTextValue; + + @override + void didUpdateWidget(CupertinoSuggestionsList oldWidget) { + super.didUpdateWidget(oldWidget); + _getSuggestions(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _getSuggestions(); + } + + @override + void initState() { + super.initState(); + + this._animationController = AnimationController( + vsync: this, + duration: widget.animationDuration, + ); + + this._suggestionsValid = widget.minCharsForSuggestions! > 0 ? true : false; + this._isLoading = false; + this._isQueued = false; + this._lastTextValue = widget.controller!.text; + + if (widget.getImmediateSuggestions) { + this._getSuggestions(); + } + + this._controllerListener = () { + // If we came here because of a change in selected text, not because of + // actual change in text + if (widget.controller!.text == this._lastTextValue) return; + + this._lastTextValue = widget.controller!.text; + + this._debounceTimer?.cancel(); + if (widget.controller!.text.length < widget.minCharsForSuggestions!) { + if (mounted) { + setState(() { + _isLoading = false; + _suggestions = null; + _suggestionsValid = true; + }); + } + return; + } else { + this._debounceTimer = Timer(widget.debounceDuration!, () async { + if (this._debounceTimer!.isActive) return; + if (_isLoading!) { + _isQueued = true; + return; + } + + await this.invalidateSuggestions(); + while (_isQueued!) { + _isQueued = false; + await this.invalidateSuggestions(); + } + }); + } + }; + + widget.controller!.addListener(this._controllerListener); + } + + Future invalidateSuggestions() async { + _suggestionsValid = false; + _getSuggestions(); + } + + Future _getSuggestions() async { + if (_suggestionsValid) return; + _suggestionsValid = true; + + if (mounted) { + setState(() { + this._animationController!.forward(from: 1.0); + + this._isLoading = true; + this._error = null; + }); + + Iterable? suggestions; + Object? error; + + try { + suggestions = + await widget.suggestionsCallback!(widget.controller!.text); + } catch (e) { + error = e; + } + + if (this.mounted) { + // if it wasn't removed in the meantime + setState(() { + double? animationStart = widget.animationStart; + // allow suggestionsCallback to return null and not throw error here + if (error != null || suggestions?.isEmpty == true) { + animationStart = 1.0; + } + this._animationController!.forward(from: animationStart); + + this._error = error; + this._isLoading = false; + this._suggestions = suggestions; + }); + } + } + } + + @override + void dispose() { + _animationController!.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool isEmpty = + this._suggestions?.length == 0 && widget.controller!.text == ""; + if ((this._suggestions == null || isEmpty) && this._isLoading == false) + return Container(); + + Widget child; + if (this._isLoading!) { + if (widget.hideOnLoading!) { + child = Container(height: 0); + } else { + child = createLoadingWidget(); + } + } else if (this._error != null) { + if (widget.hideOnError!) { + child = Container(height: 0); + } else { + child = createErrorWidget(); + } + } else if (this._suggestions!.isEmpty) { + if (widget.hideOnEmpty!) { + child = Container(height: 0); + } else { + child = createNoItemsFoundWidget(); + } + } else { + child = createSuggestionsWidget(); + } + + var animationChild = widget.transitionBuilder != null + ? widget.transitionBuilder!(context, child, this._animationController) + : SizeTransition( + axisAlignment: -1.0, + sizeFactor: CurvedAnimation( + parent: this._animationController!, + curve: Curves.fastOutSlowIn), + child: child, + ); + + BoxConstraints constraints; + if (widget.decoration!.constraints == null) { + constraints = BoxConstraints( + maxHeight: widget.suggestionsBox!.maxHeight, + ); + } else { + double maxHeight = min(widget.decoration!.constraints!.maxHeight, + widget.suggestionsBox!.maxHeight); + constraints = widget.decoration!.constraints!.copyWith( + minHeight: min(widget.decoration!.constraints!.minHeight, maxHeight), + maxHeight: maxHeight, + ); + } + + return ConstrainedBox( + constraints: constraints, + child: animationChild, + ); + } + + Widget createLoadingWidget() { + Widget child; + + if (widget.keepSuggestionsOnLoading! && this._suggestions != null) { + if (this._suggestions!.isEmpty) { + child = createNoItemsFoundWidget(); + } else { + child = createSuggestionsWidget(); + } + } else { + child = widget.loadingBuilder != null + ? widget.loadingBuilder!(context) + : Container( + decoration: BoxDecoration( + color: CupertinoColors.white, + border: Border.all( + color: CupertinoColors.extraLightBackgroundGray, + width: 1.0, + ), + ), + child: Align( + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: CupertinoActivityIndicator(), + ), + ), + ); + } + + return child; + } + + Widget createErrorWidget() { + return widget.errorBuilder != null + ? widget.errorBuilder!(context, this._error) + : Container( + decoration: BoxDecoration( + color: CupertinoColors.white, + border: Border.all( + color: CupertinoColors.extraLightBackgroundGray, + width: 1.0, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Text( + 'Error: ${this._error}', + textAlign: TextAlign.start, + style: TextStyle( + color: CupertinoColors.destructiveRed, + fontSize: 18.0, + ), + ), + ), + ); + } + + Widget createNoItemsFoundWidget() { + return widget.noItemsFoundBuilder != null + ? widget.noItemsFoundBuilder!(context) + : Container( + decoration: BoxDecoration( + color: CupertinoColors.white, + border: Border.all( + color: CupertinoColors.extraLightBackgroundGray, + width: 1.0, + ), + ), + child: Padding( + padding: const EdgeInsets.all(4.0), + child: Text( + 'No Items Found!', + textAlign: TextAlign.start, + style: TextStyle( + color: CupertinoColors.inactiveGray, + fontSize: 18.0, + ), + ), + ), + ); + } + + Widget createSuggestionsWidget() { + Widget child = Container( + decoration: BoxDecoration( + color: widget.decoration!.color != null + ? widget.decoration!.color + : CupertinoColors.white, + border: widget.decoration!.border != null + ? widget.decoration!.border + : Border.all( + color: CupertinoColors.extraLightBackgroundGray, + width: 1.0, + ), + borderRadius: widget.decoration!.borderRadius != null + ? widget.decoration!.borderRadius + : null, + ), + child: ListView( + padding: EdgeInsets.zero, + primary: false, + shrinkWrap: true, + keyboardDismissBehavior: widget.hideKeyboardOnDrag + ? ScrollViewKeyboardDismissBehavior.onDrag + : ScrollViewKeyboardDismissBehavior.manual, + reverse: widget.suggestionsBox!.direction == AxisDirection.down + ? false + : widget.suggestionsBox!.autoFlipListDirection, + children: this._suggestions!.map((T suggestion) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + child: widget.itemBuilder!(context, suggestion), + onTap: () { + widget.onSuggestionSelected!(suggestion); + }, + ); + }).toList(), + ), + ); + + if (widget.decoration!.hasScrollbar) { + child = CupertinoScrollbar(child: child); + } + + return child; + } +} \ No newline at end of file diff --git a/lib/src/keyboard_suggestion_selection_notifier.dart b/lib/src/keyboard_suggestion_selection_notifier.dart new file mode 100644 index 0000000..b98614d --- /dev/null +++ b/lib/src/keyboard_suggestion_selection_notifier.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class KeyboardSuggestionSelectionNotifier + extends ValueNotifier { + KeyboardSuggestionSelectionNotifier() : super(null); + + void onKeyboardEvent(RawKeyEvent event) { + // * we only handle key down event + if (event.runtimeType == RawKeyUpEvent) return; + + if (event.logicalKey == LogicalKeyboardKey.arrowDown || + event.logicalKey == LogicalKeyboardKey.arrowUp) { + if (value == event.logicalKey) { + notifyListeners(); + } else { + value = event.logicalKey; + } + } + } +} diff --git a/lib/src/material/field/text_field_configuration.dart b/lib/src/material/field/text_field_configuration.dart new file mode 100644 index 0000000..0bbde85 --- /dev/null +++ b/lib/src/material/field/text_field_configuration.dart @@ -0,0 +1,274 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +/// Supply an instance of this class to the [TypeAhead.textFieldConfiguration] +/// property to configure the displayed text field +class TextFieldConfiguration { + /// The decoration to show around the text field. + /// + /// Same as [TextField.decoration](https://docs.flutter.io/flutter/material/TextField/decoration.html) + final InputDecoration decoration; + + /// Controls the text being edited. + /// + /// If null, this widget will create its own [TextEditingController](https://docs.flutter.io/flutter/widgets/TextEditingController-class.html). + /// A typical use case for this field in the TypeAhead widget is to set the + /// text of the widget when a suggestion is selected. For example: + /// + /// ```dart + /// final _controller = TextEditingController(); + /// ... + /// ... + /// TypeAheadField( + /// controller: _controller, + /// ... + /// ... + /// onSuggestionSelected: (suggestion) { + /// _controller.text = suggestion['city_name']; + /// } + /// ) + /// ``` + final TextEditingController? controller; + + /// Controls whether this widget has keyboard focus. + /// + /// Same as [TextField.focusNode](https://docs.flutter.io/flutter/material/TextField/focusNode.html) + final FocusNode? focusNode; + + /// The style to use for the text being edited. + /// + /// Same as [TextField.style](https://docs.flutter.io/flutter/material/TextField/style.html) + final TextStyle? style; + + /// How the text being edited should be aligned horizontally. + /// + /// Same as [TextField.textAlign](https://docs.flutter.io/flutter/material/TextField/textAlign.html) + final TextAlign textAlign; + + /// Same as [TextField.textDirection](https://docs.flutter.io/flutter/material/TextField/textDirection.html) + /// + /// Defaults to null + final TextDirection? textDirection; + + /// Same as [TextField.textAlignVertical](https://api.flutter.dev/flutter/material/TextField/textAlignVertical.html) + final TextAlignVertical? textAlignVertical; + + /// If false the textfield is "disabled": it ignores taps and its + /// [decoration] is rendered in grey. + /// + /// Same as [TextField.enabled](https://docs.flutter.io/flutter/material/TextField/enabled.html) + final bool enabled; + + /// Whether to show input suggestions as the user types. + /// + /// Same as [TextField.enableSuggestions](https://api.flutter.dev/flutter/material/TextField/enableSuggestions.html) + final bool enableSuggestions; + + /// The type of keyboard to use for editing the text. + /// + /// Same as [TextField.keyboardType](https://docs.flutter.io/flutter/material/TextField/keyboardType.html) + final TextInputType keyboardType; + + /// Whether this text field should focus itself if nothing else is already + /// focused. + /// + /// Same as [TextField.autofocus](https://docs.flutter.io/flutter/material/TextField/autofocus.html) + final bool autofocus; + + /// Optional input validation and formatting overrides. + /// + /// Same as [TextField.inputFormatters](https://docs.flutter.io/flutter/material/TextField/inputFormatters.html) + final List? inputFormatters; + + /// Whether to enable autocorrection. + /// + /// Same as [TextField.autocorrect](https://docs.flutter.io/flutter/material/TextField/autocorrect.html) + final bool autocorrect; + + /// The maximum number of lines for the text to span, wrapping if necessary. + /// + /// Same as [TextField.maxLines](https://docs.flutter.io/flutter/material/TextField/maxLines.html) + final int? maxLines; + + /// The minimum number of lines to occupy when the content spans fewer lines. + /// + /// Same as [TextField.minLines](https://docs.flutter.io/flutter/material/TextField/minLines.html) + final int? minLines; + + /// The maximum number of characters (Unicode scalar values) to allow in the + /// text field. + /// + /// Same as [TextField.maxLength](https://docs.flutter.io/flutter/material/TextField/maxLength.html) + final int? maxLength; + + /// If true, prevents the field from allowing more than [maxLength] + /// characters. + /// + /// Same as [TextField.maxLengthEnforcement](https://api.flutter.dev/flutter/material/TextField/maxLengthEnforcement.html) + final MaxLengthEnforcement? maxLengthEnforcement; + + /// Whether to hide the text being edited (e.g., for passwords). + /// + /// Same as [TextField.obscureText](https://docs.flutter.io/flutter/material/TextField/obscureText.html) + final bool obscureText; + + /// Called when the text being edited changes. + /// + /// Same as [TextField.onChanged](https://docs.flutter.io/flutter/material/TextField/onChanged.html) + final ValueChanged? onChanged; + + /// Called when the user indicates that they are done editing the text in the + /// field. + /// + /// Same as [TextField.onSubmitted](https://docs.flutter.io/flutter/material/TextField/onSubmitted.html) + final ValueChanged? onSubmitted; + + /// The color to use when painting the cursor. + /// + /// Same as [TextField.cursorColor](https://docs.flutter.io/flutter/material/TextField/cursorColor.html) + final Color? cursorColor; + + /// How rounded the corners of the cursor should be. By default, the cursor has a null Radius + /// + /// Same as [TextField.cursorRadius](https://docs.flutter.io/flutter/material/TextField/cursorRadius.html) + final Radius? cursorRadius; + + /// How thick the cursor will be. + /// + /// Same as [TextField.cursorWidth](https://docs.flutter.io/flutter/material/TextField/cursorWidth.html) + final double cursorWidth; + + /// The appearance of the keyboard. + /// + /// Same as [TextField.keyboardAppearance](https://docs.flutter.io/flutter/material/TextField/keyboardAppearance.html) + final Brightness? keyboardAppearance; + + /// Called when the user submits editable content (e.g., user presses the "done" button on the keyboard). + /// + /// Same as [TextField.onEditingComplete](https://docs.flutter.io/flutter/material/TextField/onEditingComplete.html) + final VoidCallback? onEditingComplete; + + /// Called for each distinct tap except for every second tap of a double tap. + /// + /// Same as [TextField.onTap](https://docs.flutter.io/flutter/material/TextField/onTap.html) + final GestureTapCallback? onTap; + + /// Configures padding to edges surrounding a Scrollable when the Textfield scrolls into view. + /// + /// Same as [TextField.scrollPadding](https://docs.flutter.io/flutter/material/TextField/scrollPadding.html) + final EdgeInsets scrollPadding; + + /// Configures how the platform keyboard will select an uppercase or lowercase keyboard. + /// + /// Same as [TextField.TextCapitalization](https://docs.flutter.io/flutter/material/TextField/textCapitalization.html) + final TextCapitalization textCapitalization; + + /// The type of action button to use for the keyboard. + /// + /// Same as [TextField.textInputAction](https://docs.flutter.io/flutter/material/TextField/textInputAction.html) + final TextInputAction? textInputAction; + + final bool enableInteractiveSelection; + + /// Creates a TextFieldConfiguration + const TextFieldConfiguration({ + this.decoration = const InputDecoration(), + this.style, + this.controller, + this.onChanged, + this.onSubmitted, + this.obscureText = false, + this.maxLengthEnforcement, + this.maxLength, + this.maxLines = 1, + this.minLines, + this.textAlignVertical, + this.autocorrect = true, + this.inputFormatters, + this.autofocus = false, + this.keyboardType = TextInputType.text, + this.enabled = true, + this.enableSuggestions = true, + this.textAlign = TextAlign.start, + this.focusNode, + this.cursorColor, + this.cursorRadius, + this.textInputAction, + this.textCapitalization = TextCapitalization.none, + this.cursorWidth = 2.0, + this.keyboardAppearance, + this.onEditingComplete, + this.onTap, + this.textDirection, + this.scrollPadding = const EdgeInsets.all(20.0), + this.enableInteractiveSelection = true, + }); + + /// Copies the [TextFieldConfiguration] and only changes the specified + /// properties + TextFieldConfiguration copyWith( + {InputDecoration? decoration, + TextStyle? style, + TextEditingController? controller, + ValueChanged? onChanged, + ValueChanged? onSubmitted, + bool? obscureText, + MaxLengthEnforcement? maxLengthEnforcement, + int? maxLength, + int? maxLines, + int? minLines, + bool? autocorrect, + List? inputFormatters, + bool? autofocus, + TextInputType? keyboardType, + bool? enabled, + bool? enableSuggestions, + TextAlign? textAlign, + FocusNode? focusNode, + Color? cursorColor, + TextAlignVertical? textAlignVertical, + Radius? cursorRadius, + double? cursorWidth, + Brightness? keyboardAppearance, + VoidCallback? onEditingComplete, + GestureTapCallback? onTap, + EdgeInsets? scrollPadding, + TextCapitalization? textCapitalization, + TextDirection? textDirection, + TextInputAction? textInputAction, + bool? enableInteractiveSelection}) { + return TextFieldConfiguration( + decoration: decoration ?? this.decoration, + style: style ?? this.style, + controller: controller ?? this.controller, + onChanged: onChanged ?? this.onChanged, + onSubmitted: onSubmitted ?? this.onSubmitted, + obscureText: obscureText ?? this.obscureText, + maxLengthEnforcement: maxLengthEnforcement ?? this.maxLengthEnforcement, + maxLength: maxLength ?? this.maxLength, + maxLines: maxLines ?? this.maxLines, + minLines: minLines ?? this.minLines, + autocorrect: autocorrect ?? this.autocorrect, + inputFormatters: inputFormatters ?? this.inputFormatters, + autofocus: autofocus ?? this.autofocus, + keyboardType: keyboardType ?? this.keyboardType, + enabled: enabled ?? this.enabled, + enableSuggestions: enableSuggestions ?? this.enableSuggestions, + textAlign: textAlign ?? this.textAlign, + textAlignVertical: textAlignVertical ?? this.textAlignVertical, + focusNode: focusNode ?? this.focusNode, + cursorColor: cursorColor ?? this.cursorColor, + cursorRadius: cursorRadius ?? this.cursorRadius, + cursorWidth: cursorWidth ?? this.cursorWidth, + keyboardAppearance: keyboardAppearance ?? this.keyboardAppearance, + onEditingComplete: onEditingComplete ?? this.onEditingComplete, + onTap: onTap ?? this.onTap, + scrollPadding: scrollPadding ?? this.scrollPadding, + textCapitalization: textCapitalization ?? this.textCapitalization, + textInputAction: textInputAction ?? this.textInputAction, + textDirection: textDirection ?? this.textDirection, + enableInteractiveSelection: + enableInteractiveSelection ?? this.enableInteractiveSelection, + ); + } +} \ No newline at end of file diff --git a/lib/src/material/field/typeahead_field.dart b/lib/src/material/field/typeahead_field.dart new file mode 100644 index 0000000..2811697 --- /dev/null +++ b/lib/src/material/field/typeahead_field.dart @@ -0,0 +1,885 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; +import 'package:flutter_typeahead/src/material/field/text_field_configuration.dart'; +import 'package:flutter_typeahead/src/keyboard_suggestion_selection_notifier.dart'; +import 'package:flutter_typeahead/src/should_refresh_suggestion_focus_index_notifier.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_controller.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_list.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; +import 'package:flutter_typeahead/src/utils.dart'; + +/// # Flutter TypeAhead +/// A TypeAhead widget for Flutter, where you can show suggestions to +/// users as they type +/// +/// ## Features +/// * Shows suggestions in an overlay that floats on top of other widgets +/// * Allows you to specify what the suggestions will look like through a +/// builder function +/// * Allows you to specify what happens when the user taps a suggestion +/// * Accepts all the parameters that traditional TextFields accept, like +/// decoration, custom TextEditingController, text styling, etc. +/// * Provides two versions, a normal version and a [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +/// version that accepts validation, submitting, etc. +/// * Provides high customizability; you can customize the suggestion box decoration, +/// the loading bar, the animation, the debounce duration, etc. +/// +/// ## Installation +/// See the [installation instructions on pub](https://pub.dartlang.org/packages/flutter_typeahead#-installing-tab-). +/// +/// ## Usage examples +/// You can import the package with: +/// ```dart +/// import 'package:flutter_typeahead/flutter_typeahead.dart'; +/// ``` +/// +/// and then use it as follows: +/// +/// ### Example 1: +/// ```dart +/// TypeAheadField( +/// textFieldConfiguration: TextFieldConfiguration( +/// autofocus: true, +/// style: DefaultTextStyle.of(context).style.copyWith( +/// fontStyle: FontStyle.italic +/// ), +/// decoration: InputDecoration( +/// border: OutlineInputBorder() +/// ) +/// ), +/// suggestionsCallback: (pattern) async { +/// return await BackendService.getSuggestions(pattern); +/// }, +/// itemBuilder: (context, suggestion) { +/// return ListTile( +/// leading: Icon(Icons.shopping_cart), +/// title: Text(suggestion['name']), +/// subtitle: Text('\$${suggestion['price']}'), +/// ); +/// }, +/// onSuggestionSelected: (suggestion) { +/// Navigator.of(context).push(MaterialPageRoute( +/// builder: (context) => ProductPage(product: suggestion) +/// )); +/// }, +/// ) +/// ``` +/// In the code above, the `textFieldConfiguration` property allows us to +/// configure the displayed `TextField` as we want. In this example, we are +/// configuring the `autofocus`, `style` and `decoration` properties. +/// +/// The `suggestionsCallback` is called with the search string that the user +/// types, and is expected to return a `List` of data either synchronously or +/// asynchronously. In this example, we are calling an asynchronous function +/// called `BackendService.getSuggestions` which fetches the list of +/// suggestions. +/// +/// The `itemBuilder` is called to build a widget for each suggestion. +/// In this example, we build a simple `ListTile` that shows the name and the +/// price of the item. Please note that you shouldn't provide an `onTap` +/// callback here. The TypeAhead widget takes care of that. +/// +/// The `onSuggestionSelected` is a callback called when the user taps a +/// suggestion. In this example, when the user taps a +/// suggestion, we navigate to a page that shows us the information of the +/// tapped product. +/// +/// ### Example 2: +/// Here's another example, where we use the TypeAheadFormField inside a `Form`: +/// ```dart +/// final GlobalKey _formKey = GlobalKey(); +/// final TextEditingController _typeAheadController = TextEditingController(); +/// String _selectedCity; +/// ... +/// Form( +/// key: this._formKey, +/// child: Padding( +/// padding: EdgeInsets.all(32.0), +/// child: Column( +/// children: [ +/// Text( +/// 'What is your favorite city?' +/// ), +/// TypeAheadFormField( +/// textFieldConfiguration: TextFieldConfiguration( +/// controller: this._typeAheadController, +/// decoration: InputDecoration( +/// labelText: 'City' +/// ) +/// ), +/// suggestionsCallback: (pattern) { +/// return CitiesService.getSuggestions(pattern); +/// }, +/// itemBuilder: (context, suggestion) { +/// return ListTile( +/// title: Text(suggestion), +/// ); +/// }, +/// transitionBuilder: (context, suggestionsBox, controller) { +/// return suggestionsBox; +/// }, +/// onSuggestionSelected: (suggestion) { +/// this._typeAheadController.text = suggestion; +/// }, +/// validator: (value) { +/// if (value.isEmpty) { +/// return 'Please select a city'; +/// } +/// }, +/// onSaved: (value) => this._selectedCity = value, +/// ), +/// SizedBox(height: 10.0,), +/// RaisedButton( +/// child: Text('Submit'), +/// onPressed: () { +/// if (this._formKey.currentState.validate()) { +/// this._formKey.currentState.save(); +/// Scaffold.of(context).showSnackBar(SnackBar( +/// content: Text('Your Favorite City is ${this._selectedCity}') +/// )); +/// } +/// }, +/// ) +/// ], +/// ), +/// ), +/// ) +/// ``` +/// Here, we assign to the `controller` property of the `textFieldConfiguration` +/// a `TextEditingController` that we call `_typeAheadController`. +/// We use this controller in the `onSuggestionSelected` callback to set the +/// value of the `TextField` to the selected suggestion. +/// +/// The `validator` callback can be used like any `FormField.validator` +/// function. In our example, it checks whether a value has been entered, +/// and displays an error message if not. The `onSaved` callback is used to +/// save the value of the field to the `_selectedCity` member variable. +/// +/// The `transitionBuilder` allows us to customize the animation of the +/// suggestion box. In this example, we are returning the suggestionsBox +/// immediately, meaning that we don't want any animation. +/// +/// ## Customizations +/// TypeAhead widgets consist of a TextField and a suggestion box that shows +/// as the user types. Both are highly customizable +/// +/// ### Customizing the TextField +/// You can customize the text field using the `textFieldConfiguration` property. +/// You provide this property with an instance of `TextFieldConfiguration`, +/// which allows you to configure all the usual properties of `TextField`, like +/// `decoration`, `style`, `controller`, `focusNode`, `autofocus`, `enabled`, +/// etc. +/// +/// ### Customizing the Suggestions Box +/// TypeAhead provides default configurations for the suggestions box. You can, +/// however, override most of them. +/// +/// #### Customizing the loader, the error and the "no items found" message +/// You can use the [loadingBuilder], [errorBuilder] and [noItemsFoundBuilder] to +/// customize their corresponding widgets. For example, to show a custom error +/// widget: +/// ```dart +/// errorBuilder: (BuildContext context, Object error) => +/// Text( +/// '$error', +/// style: TextStyle( +/// color: Theme.of(context).errorColor +/// ) +/// ) +/// ``` +/// #### Customizing the animation +/// You can customize the suggestion box animation through 3 parameters: the +/// `animationDuration`, the `animationStart`, and the `transitionBuilder`. +/// +/// The `animationDuration` specifies how long the animation should take, while the +/// `animationStart` specified what point (between 0.0 and 1.0) the animation +/// should start from. The `transitionBuilder` accepts the `suggestionsBox` and +/// `animationController` as parameters, and should return a widget that uses +/// the `animationController` to animate the display of the `suggestionsBox`. +/// For example: +/// ```dart +/// transitionBuilder: (context, suggestionsBox, animationController) => +/// FadeTransition( +/// child: suggestionsBox, +/// opacity: CurvedAnimation( +/// parent: animationController, +/// curve: Curves.fastOutSlowIn +/// ), +/// ) +/// ``` +/// This uses [FadeTransition](https://docs.flutter.io/flutter/widgets/FadeTransition-class.html) +/// to fade the `suggestionsBox` into the view. Note how the +/// `animationController` was provided as the parent of the animation. +/// +/// In order to fully remove the animation, `transitionBuilder` should simply +/// return the `suggestionsBox`. This callback could also be used to wrap the +/// `suggestionsBox` with any desired widgets, not necessarily for animation. +/// +/// #### Customizing the debounce duration +/// The suggestions box does not fire for each character the user types. Instead, +/// we wait until the user is idle for a duration of time, and then call the +/// `suggestionsCallback`. The duration defaults to 300 milliseconds, but can be +/// configured using the `debounceDuration` parameter. +/// +/// #### Customizing the offset of the suggestions box +/// By default, the suggestions box is displayed 5 pixels below the `TextField`. +/// You can change this by changing the `suggestionsBoxVerticalOffset` property. +/// +/// #### Customizing the decoration of the suggestions box +/// You can also customize the decoration of the suggestions box using the +/// `suggestionsBoxDecoration` property. For example, to remove the elevation +/// of the suggestions box, you can write: +/// ```dart +/// suggestionsBoxDecoration: SuggestionsBoxDecoration( +/// elevation: 0.0 +/// ) +/// ``` +/// A [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +/// implementation of [TypeAheadField], that allows the value to be saved, +/// validated, etc. +/// +/// See also: +/// +/// * [TypeAheadField], A [TextField](https://docs.flutter.io/flutter/material/TextField-class.html) +/// that displays a list of suggestions as the user types +class TypeAheadField extends StatefulWidget { + /// Called with the search pattern to get the search suggestions. + /// + /// This callback must not be null. It is be called by the TypeAhead widget + /// and provided with the search pattern. It should return a [List](https://api.dartlang.org/stable/2.0.0/dart-core/List-class.html) + /// of suggestions either synchronously, or asynchronously (as the result of a + /// [Future](https://api.dartlang.org/stable/dart-async/Future-class.html)). + /// Typically, the list of suggestions should not contain more than 4 or 5 + /// entries. These entries will then be provided to [itemBuilder] to display + /// the suggestions. + /// + /// Example: + /// ```dart + /// suggestionsCallback: (pattern) async { + /// return await _getSuggestions(pattern); + /// } + /// ``` + final SuggestionsCallback suggestionsCallback; + + /// Called when a suggestion is tapped. + /// + /// This callback must not be null. It is called by the TypeAhead widget and + /// provided with the value of the tapped suggestion. + /// + /// For example, you might want to navigate to a specific view when the user + /// tabs a suggestion: + /// ```dart + /// onSuggestionSelected: (suggestion) { + /// Navigator.of(context).push(MaterialPageRoute( + /// builder: (context) => SearchResult( + /// searchItem: suggestion + /// ) + /// )); + /// } + /// ``` + /// + /// Or to set the value of the text field: + /// ```dart + /// onSuggestionSelected: (suggestion) { + /// _controller.text = suggestion['name']; + /// } + /// ``` + final SuggestionSelectionCallback onSuggestionSelected; + + /// Called for each suggestion returned by [suggestionsCallback] to build the + /// corresponding widget. + /// + /// This callback must not be null. It is called by the TypeAhead widget for + /// each suggestion, and expected to build a widget to display this + /// suggestion's info. For example: + /// + /// ```dart + /// itemBuilder: (context, suggestion) { + /// return ListTile( + /// title: Text(suggestion['name']), + /// subtitle: Text('USD' + suggestion['price'].toString()) + /// ); + /// } + /// ``` + final ItemBuilder itemBuilder; + + /// used to control the scroll behavior of item-builder list + final ScrollController? scrollController; + + /// The decoration of the material sheet that contains the suggestions. + /// + /// If null, default decoration with an elevation of 4.0 is used + /// + + final SuggestionsBoxDecoration suggestionsBoxDecoration; + + /// Used to control the `_SuggestionsBox`. Allows manual control to + /// open, close, toggle, or resize the `_SuggestionsBox`. + final SuggestionsBoxController? suggestionsBoxController; + + /// The duration to wait after the user stops typing before calling + /// [suggestionsCallback] + /// + /// This is useful, because, if not set, a request for suggestions will be + /// sent for every character that the user types. + /// + /// This duration is set by default to 300 milliseconds + final Duration debounceDuration; + + /// Called when waiting for [suggestionsCallback] to return. + /// + /// It is expected to return a widget to display while waiting. + /// For example: + /// ```dart + /// (BuildContext context) { + /// return Text('Loading...'); + /// } + /// ``` + /// + /// If not specified, a [CircularProgressIndicator](https://docs.flutter.io/flutter/material/CircularProgressIndicator-class.html) is shown + final WidgetBuilder? loadingBuilder; + + /// Called when [suggestionsCallback] returns an empty array. + /// + /// It is expected to return a widget to display when no suggestions are + /// avaiable. + /// For example: + /// ```dart + /// (BuildContext context) { + /// return Text('No Items Found!'); + /// } + /// ``` + /// + /// If not specified, a simple text is shown + final WidgetBuilder? noItemsFoundBuilder; + + /// Called when [suggestionsCallback] throws an exception. + /// + /// It is called with the error object, and expected to return a widget to + /// display when an exception is thrown + /// For example: + /// ```dart + /// (BuildContext context, error) { + /// return Text('$error'); + /// } + /// ``` + /// + /// If not specified, the error is shown in [ThemeData.errorColor](https://docs.flutter.io/flutter/material/ThemeData/errorColor.html) + final ErrorBuilder? errorBuilder; + + /// Called to display animations when [suggestionsCallback] returns suggestions + /// + /// It is provided with the suggestions box instance and the animation + /// controller, and expected to return some animation that uses the controller + /// to display the suggestion box. + /// + /// For example: + /// ```dart + /// transitionBuilder: (context, suggestionsBox, animationController) { + /// return FadeTransition( + /// child: suggestionsBox, + /// opacity: CurvedAnimation( + /// parent: animationController, + /// curve: Curves.fastOutSlowIn + /// ), + /// ); + /// } + /// ``` + /// This argument is best used with [animationDuration] and [animationStart] + /// to fully control the animation. + /// + /// To fully remove the animation, just return `suggestionsBox` + /// + /// If not specified, a [SizeTransition](https://docs.flutter.io/flutter/widgets/SizeTransition-class.html) is shown. + final AnimationTransitionBuilder? transitionBuilder; + + /// The duration that [transitionBuilder] animation takes. + /// + /// This argument is best used with [transitionBuilder] and [animationStart] + /// to fully control the animation. + /// + /// Defaults to 500 milliseconds. + final Duration animationDuration; + + /// Determine the [SuggestionBox]'s direction. + /// + /// If [AxisDirection.down], the [SuggestionBox] will be below the [TextField] + /// and the [_SuggestionsList] will grow **down**. + /// + /// If [AxisDirection.up], the [SuggestionBox] will be above the [TextField] + /// and the [_SuggestionsList] will grow **up**. + /// + /// [AxisDirection.left] and [AxisDirection.right] are not allowed. + final AxisDirection direction; + + /// The value at which the [transitionBuilder] animation starts. + /// + /// This argument is best used with [transitionBuilder] and [animationDuration] + /// to fully control the animation. + /// + /// Defaults to 0.25. + final double animationStart; + + /// The configuration of the [TextField](https://docs.flutter.io/flutter/material/TextField-class.html) + /// that the TypeAhead widget displays + final TextFieldConfiguration textFieldConfiguration; + + /// How far below the text field should the suggestions box be + /// + /// Defaults to 5.0 + final double suggestionsBoxVerticalOffset; + + /// If set to true, suggestions will be fetched immediately when the field is + /// added to the view. + /// + /// But the suggestions box will only be shown when the field receives focus. + /// To make the field receive focus immediately, you can set the `autofocus` + /// property in the [textFieldConfiguration] to true + /// + /// Defaults to false + final bool getImmediateSuggestions; + + /// If set to true, no loading box will be shown while suggestions are + /// being fetched. [loadingBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnLoading; + + /// If set to true, nothing will be shown if there are no results. + /// [noItemsFoundBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnEmpty; + + /// If set to true, nothing will be shown if there is an error. + /// [errorBuilder] will also be ignored. + /// + /// Defaults to false. + final bool hideOnError; + + /// If set to false, the suggestions box will stay opened after + /// the keyboard is closed. + /// + /// Defaults to true. + final bool hideSuggestionsOnKeyboardHide; + + /// If set to false, the suggestions box will show a circular + /// progress indicator when retrieving suggestions. + /// + /// Defaults to true. + final bool keepSuggestionsOnLoading; + + /// If set to true, the suggestions box will remain opened even after + /// selecting a suggestion. + /// + /// Note that if this is enabled, the only way + /// to close the suggestions box is either manually via the + /// `SuggestionsBoxController` or when the user closes the software + /// keyboard if `hideSuggestionsOnKeyboardHide` is set to true. Users + /// with a physical keyboard will be unable to close the + /// box without a manual way via `SuggestionsBoxController`. + /// + /// Defaults to false. + final bool keepSuggestionsOnSuggestionSelected; + + /// If set to true, in the case where the suggestions box has less than + /// _SuggestionsBoxController.minOverlaySpace to grow in the desired [direction], the direction axis + /// will be temporarily flipped if there's more room available in the opposite + /// direction. + /// + /// Defaults to false + final bool autoFlipDirection; + + /// If set to false, suggestion list will not be reversed according to the + /// [autoFlipDirection] property. + /// + /// Defaults to true. + final bool autoFlipListDirection; + + final bool hideKeyboard; + + /// The minimum number of characters which must be entered before + /// [suggestionsCallback] is triggered. + /// + /// Defaults to 0. + final int minCharsForSuggestions; + + /// If set to true and if the user scrolls through the suggestion list, hide the keyboard automatically. + /// If set to false, the keyboard remains visible. + /// Throws an exception, if hideKeyboardOnDrag and hideSuggestionsOnKeyboardHide are both set to true as + /// they are mutual exclusive. + /// + /// Defaults to false + final bool hideKeyboardOnDrag; + + // Adds a callback for the suggestion box opening or closing + final void Function(bool)? onSuggestionsBoxToggle; + + /// Creates a [TypeAheadField] + TypeAheadField({ + required this.suggestionsCallback, + required this.itemBuilder, + required this.onSuggestionSelected, + this.textFieldConfiguration = const TextFieldConfiguration(), + this.suggestionsBoxDecoration = const SuggestionsBoxDecoration(), + this.debounceDuration = const Duration(milliseconds: 300), + this.suggestionsBoxController, + this.scrollController, + this.loadingBuilder, + this.noItemsFoundBuilder, + this.errorBuilder, + this.transitionBuilder, + this.animationStart = 0.25, + this.animationDuration = const Duration(milliseconds: 500), + this.getImmediateSuggestions = false, + this.suggestionsBoxVerticalOffset = 5.0, + this.direction = AxisDirection.down, + this.hideOnLoading = false, + this.hideOnEmpty = false, + this.hideOnError = false, + this.hideSuggestionsOnKeyboardHide = true, + this.keepSuggestionsOnLoading = true, + this.keepSuggestionsOnSuggestionSelected = false, + this.autoFlipDirection = false, + this.autoFlipListDirection = true, + this.hideKeyboard = false, + this.minCharsForSuggestions = 0, + this.onSuggestionsBoxToggle, + this.hideKeyboardOnDrag = false, + super.key, + }) : assert(animationStart >= 0.0 && animationStart <= 1.0), + assert( + direction == AxisDirection.down || direction == AxisDirection.up), + assert(minCharsForSuggestions >= 0), + assert(!hideKeyboardOnDrag || + hideKeyboardOnDrag && !hideSuggestionsOnKeyboardHide); + + @override + _TypeAheadFieldState createState() => _TypeAheadFieldState(); +} + +class _TypeAheadFieldState extends State> + with WidgetsBindingObserver { + FocusNode? _focusNode; + final KeyboardSuggestionSelectionNotifier + _keyboardSuggestionSelectionNotifier = + KeyboardSuggestionSelectionNotifier(); + TextEditingController? _textEditingController; + SuggestionsBox? _suggestionsBox; + + TextEditingController? get _effectiveController => + widget.textFieldConfiguration.controller ?? _textEditingController; + FocusNode? get _effectiveFocusNode => + widget.textFieldConfiguration.focusNode ?? _focusNode; + late VoidCallback _focusNodeListener; + + final LayerLink _layerLink = LayerLink(); + + // Timer that resizes the suggestion box on each tick. Only active when the user is scrolling. + Timer? _resizeOnScrollTimer; + // The rate at which the suggestion box will resize when the user is scrolling + final Duration _resizeOnScrollRefreshRate = const Duration(milliseconds: 500); + // Will have a value if the typeahead is inside a scrollable widget + ScrollPosition? _scrollPosition; + + // Keyboard detection + final Stream? _keyboardVisibility = + (supportedPlatform) ? KeyboardVisibilityController().onChange : null; + late StreamSubscription? _keyboardVisibilitySubscription; + + bool _areSuggestionsFocused = false; + late final _shouldRefreshSuggestionsFocusIndex = + ShouldRefreshSuggestionFocusIndexNotifier( + textFieldFocusNode: _effectiveFocusNode); + + @override + void didChangeMetrics() { + // Catch keyboard event and orientation change; resize suggestions list + this._suggestionsBox!.onChangeMetrics(); + } + + @override + void dispose() { + this._suggestionsBox!.close(); + this._suggestionsBox!.widgetMounted = false; + WidgetsBinding.instance.removeObserver(this); + _keyboardVisibilitySubscription?.cancel(); + _effectiveFocusNode!.removeListener(_focusNodeListener); + _focusNode?.dispose(); + _resizeOnScrollTimer?.cancel(); + _scrollPosition?.removeListener(_scrollResizeListener); + _textEditingController?.dispose(); + _keyboardSuggestionSelectionNotifier.dispose(); + super.dispose(); + } + + KeyEventResult _onKeyEvent(FocusNode _, RawKeyEvent event) { + if (event.isKeyPressed(LogicalKeyboardKey.arrowUp) || + event.isKeyPressed(LogicalKeyboardKey.arrowDown)) { + // do nothing to avoid puzzling users until keyboard arrow nav is implemented + } else { + _keyboardSuggestionSelectionNotifier.onKeyboardEvent(event); + } + return KeyEventResult.ignored; + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + + if (widget.textFieldConfiguration.controller == null) { + this._textEditingController = TextEditingController(); + } + + final textFieldConfigurationFocusNode = + widget.textFieldConfiguration.focusNode; + if (textFieldConfigurationFocusNode == null) { + this._focusNode = FocusNode(onKey: _onKeyEvent); + } else if (textFieldConfigurationFocusNode.onKey == null) { + // * we add the _onKeyEvent callback to the textFieldConfiguration focusNode + textFieldConfigurationFocusNode.onKey = ((node, event) { + final keyEventResult = _onKeyEvent(node, event); + return keyEventResult; + }); + } else { + final onKeyCopy = textFieldConfigurationFocusNode.onKey!; + textFieldConfigurationFocusNode.onKey = ((node, event) { + _onKeyEvent(node, event); + return onKeyCopy(node, event); + }); + } + + this._suggestionsBox = SuggestionsBox( + context, + widget.direction, + widget.autoFlipDirection, + widget.autoFlipListDirection, + ); + + widget.suggestionsBoxController?.suggestionsBox = this._suggestionsBox; + widget.suggestionsBoxController?.effectiveFocusNode = + this._effectiveFocusNode; + + this._focusNodeListener = () { + if (_effectiveFocusNode!.hasFocus) { + this._suggestionsBox!.open(); + } else if (!_areSuggestionsFocused) { + if (widget.hideSuggestionsOnKeyboardHide) { + this._suggestionsBox!.close(); + } + } + + widget.onSuggestionsBoxToggle?.call(this._suggestionsBox!.isOpened); + }; + + this._effectiveFocusNode!.addListener(_focusNodeListener); + + // hide suggestions box on keyboard closed + this._keyboardVisibilitySubscription = + _keyboardVisibility?.listen((bool isVisible) { + if (widget.hideSuggestionsOnKeyboardHide && !isVisible) { + _effectiveFocusNode!.unfocus(); + } + }); + + WidgetsBinding.instance.addPostFrameCallback((duration) { + if (mounted) { + this._initOverlayEntry(); + // calculate initial suggestions list size + this._suggestionsBox!.resize(); + + // in case we already missed the focus event + if (this._effectiveFocusNode!.hasFocus) { + this._suggestionsBox!.open(); + } + } + }); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + final scrollableState = Scrollable.maybeOf(context); + if (scrollableState != null) { + // The TypeAheadField is inside a scrollable widget + _scrollPosition = scrollableState.position; + + _scrollPosition!.removeListener(_scrollResizeListener); + _scrollPosition!.isScrollingNotifier.addListener(_scrollResizeListener); + } + } + + void _scrollResizeListener() { + bool isScrolling = _scrollPosition!.isScrollingNotifier.value; + _resizeOnScrollTimer?.cancel(); + if (isScrolling) { + // Scroll started + _resizeOnScrollTimer = + Timer.periodic(_resizeOnScrollRefreshRate, (timer) { + _suggestionsBox!.resize(); + }); + } else { + // Scroll finished + _suggestionsBox!.resize(); + } + } + + void _initOverlayEntry() { + this._suggestionsBox!.overlayEntry = OverlayEntry(builder: (context) { + void giveTextFieldFocus() { + _effectiveFocusNode?.requestFocus(); + _areSuggestionsFocused = false; + } + + void onSuggestionFocus() { + if (!_areSuggestionsFocused) { + _areSuggestionsFocused = true; + } + } + + final suggestionsList = SuggestionsList( + suggestionsBox: _suggestionsBox, + decoration: widget.suggestionsBoxDecoration, + debounceDuration: widget.debounceDuration, + controller: this._effectiveController, + loadingBuilder: widget.loadingBuilder, + scrollController: widget.scrollController, + noItemsFoundBuilder: widget.noItemsFoundBuilder, + errorBuilder: widget.errorBuilder, + transitionBuilder: widget.transitionBuilder, + suggestionsCallback: widget.suggestionsCallback, + animationDuration: widget.animationDuration, + animationStart: widget.animationStart, + getImmediateSuggestions: widget.getImmediateSuggestions, + onSuggestionSelected: (T selection) { + if (!widget.keepSuggestionsOnSuggestionSelected) { + this._effectiveFocusNode!.unfocus(); + this._suggestionsBox!.close(); + } + widget.onSuggestionSelected(selection); + }, + itemBuilder: widget.itemBuilder, + direction: _suggestionsBox!.direction, + hideOnLoading: widget.hideOnLoading, + hideOnEmpty: widget.hideOnEmpty, + hideOnError: widget.hideOnError, + keepSuggestionsOnLoading: widget.keepSuggestionsOnLoading, + minCharsForSuggestions: widget.minCharsForSuggestions, + keyboardSuggestionSelectionNotifier: + _keyboardSuggestionSelectionNotifier, + shouldRefreshSuggestionFocusIndexNotifier: + _shouldRefreshSuggestionsFocusIndex, + giveTextFieldFocus: giveTextFieldFocus, + onSuggestionFocus: onSuggestionFocus, + onKeyEvent: _onKeyEvent, + hideKeyboardOnDrag: widget.hideKeyboardOnDrag); + + double w = _suggestionsBox!.textBoxWidth; + if (widget.suggestionsBoxDecoration.constraints != null) { + if (widget.suggestionsBoxDecoration.constraints!.minWidth != 0.0 && + widget.suggestionsBoxDecoration.constraints!.maxWidth != + double.infinity) { + w = (widget.suggestionsBoxDecoration.constraints!.minWidth + + widget.suggestionsBoxDecoration.constraints!.maxWidth) / + 2; + } else if (widget.suggestionsBoxDecoration.constraints!.minWidth != + 0.0 && + widget.suggestionsBoxDecoration.constraints!.minWidth > w) { + w = widget.suggestionsBoxDecoration.constraints!.minWidth; + } else if (widget.suggestionsBoxDecoration.constraints!.maxWidth != + double.infinity && + widget.suggestionsBoxDecoration.constraints!.maxWidth < w) { + w = widget.suggestionsBoxDecoration.constraints!.maxWidth; + } + } + + final Widget compositedFollower = CompositedTransformFollower( + link: this._layerLink, + showWhenUnlinked: false, + offset: Offset( + widget.suggestionsBoxDecoration.offsetX, + _suggestionsBox!.direction == AxisDirection.down + ? _suggestionsBox!.textBoxHeight + + widget.suggestionsBoxVerticalOffset + : _suggestionsBox!.directionUpOffset), + child: _suggestionsBox!.direction == AxisDirection.down + ? suggestionsList + : FractionalTranslation( + translation: Offset(0.0, -1.0), // visually flips list to go up + child: suggestionsList, + ), + ); + + // When wrapped in the Positioned widget, the suggestions box widget + // is placed before the Scaffold semantically. In order to have the + // suggestions box navigable from the search input or keyboard, + // Semantics > Align > ConstrainedBox are needed. This does not change + // the style visually. However, when VO/TB are not enabled it is + // necessary to use the Positioned widget to allow the elements to be + // properly tappable. + return MediaQuery.of(context).accessibleNavigation + ? Semantics( + container: true, + child: Align( + alignment: Alignment.topLeft, + child: ConstrainedBox( + constraints: BoxConstraints(maxWidth: w), + child: compositedFollower, + ), + ), + ) + : Positioned( + width: w, + child: compositedFollower, + ); + }); + } + + @override + Widget build(BuildContext context) { + return CompositedTransformTarget( + link: this._layerLink, + child: TextField( + focusNode: this._effectiveFocusNode, + controller: this._effectiveController, + decoration: widget.textFieldConfiguration.decoration, + style: widget.textFieldConfiguration.style, + textAlign: widget.textFieldConfiguration.textAlign, + enabled: widget.textFieldConfiguration.enabled, + keyboardType: widget.textFieldConfiguration.keyboardType, + autofocus: widget.textFieldConfiguration.autofocus, + inputFormatters: widget.textFieldConfiguration.inputFormatters, + autocorrect: widget.textFieldConfiguration.autocorrect, + maxLines: widget.textFieldConfiguration.maxLines, + textAlignVertical: widget.textFieldConfiguration.textAlignVertical, + minLines: widget.textFieldConfiguration.minLines, + maxLength: widget.textFieldConfiguration.maxLength, + maxLengthEnforcement: + widget.textFieldConfiguration.maxLengthEnforcement, + obscureText: widget.textFieldConfiguration.obscureText, + onChanged: widget.textFieldConfiguration.onChanged, + onSubmitted: widget.textFieldConfiguration.onSubmitted, + onEditingComplete: widget.textFieldConfiguration.onEditingComplete, + onTap: widget.textFieldConfiguration.onTap, +// onTapOutside: (_) {}, + scrollPadding: widget.textFieldConfiguration.scrollPadding, + textInputAction: widget.textFieldConfiguration.textInputAction, + textCapitalization: widget.textFieldConfiguration.textCapitalization, + keyboardAppearance: widget.textFieldConfiguration.keyboardAppearance, + cursorWidth: widget.textFieldConfiguration.cursorWidth, + cursorRadius: widget.textFieldConfiguration.cursorRadius, + cursorColor: widget.textFieldConfiguration.cursorColor, + textDirection: widget.textFieldConfiguration.textDirection, + enableInteractiveSelection: + widget.textFieldConfiguration.enableInteractiveSelection, + readOnly: widget.hideKeyboard, + ), + ); + } +} diff --git a/lib/src/material/field/typeahead_form_field.dart b/lib/src/material/field/typeahead_form_field.dart new file mode 100644 index 0000000..d93a190 --- /dev/null +++ b/lib/src/material/field/typeahead_form_field.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/src/material/field/text_field_configuration.dart'; +import 'package:flutter_typeahead/src/material/field/typeahead_field.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_controller.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; + + +/// A [FormField](https://docs.flutter.io/flutter/widgets/FormField-class.html) +/// implementation of [TypeAheadField], that allows the value to be saved, +/// validated, etc. +/// +/// See also: +/// +/// * [TypeAheadField], A [TextField](https://docs.flutter.io/flutter/material/TextField-class.html) +/// that displays a list of suggestions as the user types +class TypeAheadFormField extends FormField { + /// The configuration of the [TextField](https://docs.flutter.io/flutter/material/TextField-class.html) + /// that the TypeAhead widget displays + final TextFieldConfiguration textFieldConfiguration; + + // Adds a callback for resetting the form field + final void Function()? onReset; + + /// Creates a [TypeAheadFormField] + TypeAheadFormField( + {Key? key, + String? initialValue, + bool getImmediateSuggestions = false, + @Deprecated('Use autovalidateMode parameter which provides more specific ' + 'behavior related to auto validation. ' + 'This feature was deprecated after Flutter v1.19.0.') + bool autovalidate = false, + bool enabled = true, + AutovalidateMode autovalidateMode = AutovalidateMode.disabled, + FormFieldSetter? onSaved, + this.onReset, + FormFieldValidator? validator, + ErrorBuilder? errorBuilder, + WidgetBuilder? noItemsFoundBuilder, + WidgetBuilder? loadingBuilder, + void Function(bool)? onSuggestionsBoxToggle, + Duration debounceDuration = const Duration(milliseconds: 300), + SuggestionsBoxDecoration suggestionsBoxDecoration = + const SuggestionsBoxDecoration(), + SuggestionsBoxController? suggestionsBoxController, + required SuggestionSelectionCallback onSuggestionSelected, + required ItemBuilder itemBuilder, + required SuggestionsCallback suggestionsCallback, + double suggestionsBoxVerticalOffset = 5.0, + this.textFieldConfiguration = const TextFieldConfiguration(), + AnimationTransitionBuilder? transitionBuilder, + Duration animationDuration = const Duration(milliseconds: 500), + double animationStart = 0.25, + AxisDirection direction = AxisDirection.down, + bool hideOnLoading = false, + bool hideOnEmpty = false, + bool hideOnError = false, + bool hideSuggestionsOnKeyboardHide = true, + bool keepSuggestionsOnLoading = true, + bool keepSuggestionsOnSuggestionSelected = false, + bool autoFlipDirection = false, + bool autoFlipListDirection = true, + bool hideKeyboard = false, + int minCharsForSuggestions = 0, + bool hideKeyboardOnDrag = false}) + : assert( + initialValue == null || textFieldConfiguration.controller == null), + assert(minCharsForSuggestions >= 0), + super( + key: key, + onSaved: onSaved, + validator: validator, + initialValue: textFieldConfiguration.controller != null + ? textFieldConfiguration.controller!.text + : (initialValue ?? ''), + enabled: enabled, + autovalidateMode: autovalidateMode, + builder: (FormFieldState field) { + final _TypeAheadFormFieldState state = + field as _TypeAheadFormFieldState; + + return TypeAheadField( + getImmediateSuggestions: getImmediateSuggestions, + transitionBuilder: transitionBuilder, + errorBuilder: errorBuilder, + noItemsFoundBuilder: noItemsFoundBuilder, + loadingBuilder: loadingBuilder, + debounceDuration: debounceDuration, + suggestionsBoxDecoration: suggestionsBoxDecoration, + suggestionsBoxController: suggestionsBoxController, + textFieldConfiguration: textFieldConfiguration.copyWith( + decoration: textFieldConfiguration.decoration + .copyWith(errorText: state.errorText), + onChanged: (text) { + state.didChange(text); + textFieldConfiguration.onChanged?.call(text); + }, + controller: state._effectiveController, + ), + suggestionsBoxVerticalOffset: suggestionsBoxVerticalOffset, + onSuggestionSelected: onSuggestionSelected, + onSuggestionsBoxToggle: onSuggestionsBoxToggle, + itemBuilder: itemBuilder, + suggestionsCallback: suggestionsCallback, + animationStart: animationStart, + animationDuration: animationDuration, + direction: direction, + hideOnLoading: hideOnLoading, + hideOnEmpty: hideOnEmpty, + hideOnError: hideOnError, + hideSuggestionsOnKeyboardHide: hideSuggestionsOnKeyboardHide, + keepSuggestionsOnLoading: keepSuggestionsOnLoading, + keepSuggestionsOnSuggestionSelected: + keepSuggestionsOnSuggestionSelected, + autoFlipDirection: autoFlipDirection, + autoFlipListDirection: autoFlipListDirection, + hideKeyboard: hideKeyboard, + minCharsForSuggestions: minCharsForSuggestions, + hideKeyboardOnDrag: hideKeyboardOnDrag, + ); + }); + + @override + _TypeAheadFormFieldState createState() => _TypeAheadFormFieldState(); +} + +class _TypeAheadFormFieldState extends FormFieldState { + TextEditingController? _controller; + + TextEditingController? get _effectiveController => + widget.textFieldConfiguration.controller ?? _controller; + + @override + TypeAheadFormField get widget => super.widget as TypeAheadFormField; + + @override + void initState() { + super.initState(); + if (widget.textFieldConfiguration.controller == null) { + _controller = TextEditingController(text: widget.initialValue); + } else { + widget.textFieldConfiguration.controller! + .addListener(_handleControllerChanged); + } + } + + @override + void didUpdateWidget(TypeAheadFormField oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.textFieldConfiguration.controller != + oldWidget.textFieldConfiguration.controller) { + oldWidget.textFieldConfiguration.controller + ?.removeListener(_handleControllerChanged); + widget.textFieldConfiguration.controller + ?.addListener(_handleControllerChanged); + + if (oldWidget.textFieldConfiguration.controller != null && + widget.textFieldConfiguration.controller == null) + _controller = TextEditingController.fromValue( + oldWidget.textFieldConfiguration.controller!.value); + if (widget.textFieldConfiguration.controller != null) { + setValue(widget.textFieldConfiguration.controller!.text); + if (oldWidget.textFieldConfiguration.controller == null) + _controller = null; + } + } + } + + @override + void dispose() { + widget.textFieldConfiguration.controller + ?.removeListener(_handleControllerChanged); + super.dispose(); + } + + @override + void reset() { + super.reset(); + setState(() { + _effectiveController!.text = widget.initialValue!; + if (widget.onReset != null) { + widget.onReset!(); + } + }); + } + + void _handleControllerChanged() { + // Suppress changes that originated from within this class. + // + // In the case where a controller has been passed in to this widget, we + // register this change listener. In these cases, we'll also receive change + // notifications for changes originating from within this class -- for + // example, the reset() method. In such cases, the FormField value will + // already have been set. + if (_effectiveController!.text != value) + didChange(_effectiveController!.text); + } +} \ No newline at end of file diff --git a/lib/src/material/suggestions_box/suggestions_box.dart b/lib/src/material/suggestions_box/suggestions_box.dart new file mode 100644 index 0000000..176abec --- /dev/null +++ b/lib/src/material/suggestions_box/suggestions_box.dart @@ -0,0 +1,223 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/src/material/field/typeahead_field.dart'; + +class SuggestionsBox { + static const int waitMetricsTimeoutMillis = 1000; + static const double minOverlaySpace = 64.0; + + final BuildContext context; + final AxisDirection desiredDirection; + final bool autoFlipDirection; + final bool autoFlipListDirection; + + OverlayEntry? overlayEntry; + AxisDirection direction; + + bool isOpened = false; + bool widgetMounted = true; + double maxHeight = 300.0; + double textBoxWidth = 100.0; + double textBoxHeight = 100.0; + late double directionUpOffset; + + SuggestionsBox( + this.context, + this.direction, + this.autoFlipDirection, + this.autoFlipListDirection, + ) : desiredDirection = direction; + + void open() { + if (this.isOpened) return; + assert(this.overlayEntry != null); + resize(); + Overlay.of(context).insert(this.overlayEntry!); + this.isOpened = true; + } + + void close() { + if (!this.isOpened) return; + assert(this.overlayEntry != null); + this.overlayEntry!.remove(); + this.isOpened = false; + } + + void toggle() { + if (this.isOpened) { + this.close(); + } else { + this.open(); + } + } + + MediaQuery? _findRootMediaQuery() { + MediaQuery? rootMediaQuery; + context.visitAncestorElements((element) { + if (element.widget is MediaQuery) { + rootMediaQuery = element.widget as MediaQuery; + } + return true; + }); + + return rootMediaQuery; + } + + /// Delays until the keyboard has toggled or the orientation has fully changed + Future _waitChangeMetrics() async { + if (widgetMounted) { + // initial viewInsets which are before the keyboard is toggled + EdgeInsets initial = MediaQuery.of(context).viewInsets; + // initial MediaQuery for orientation change + MediaQuery? initialRootMediaQuery = _findRootMediaQuery(); + + int timer = 0; + // viewInsets or MediaQuery have changed once keyboard has toggled or orientation has changed + while (widgetMounted && timer < waitMetricsTimeoutMillis) { + // TODO: reduce delay if showDialog ever exposes detection of animation end + await Future.delayed(const Duration(milliseconds: 170)); + timer += 170; + + if (widgetMounted && + (MediaQuery.of(context).viewInsets != initial || + _findRootMediaQuery() != initialRootMediaQuery)) { + return true; + } + } + } + + return false; + } + + void resize() { + // check to see if widget is still mounted + // user may have closed the widget with the keyboard still open + if (widgetMounted) { + _adjustMaxHeightAndOrientation(); + overlayEntry!.markNeedsBuild(); + } + } + + // See if there's enough room in the desired direction for the overlay to display + // correctly. If not, try the opposite direction if things look more roomy there + void _adjustMaxHeightAndOrientation() { + TypeAheadField widget = context.widget as TypeAheadField; + + RenderBox? box = context.findRenderObject() as RenderBox?; + if (box == null || box.hasSize == false) { + return; + } + + textBoxWidth = box.size.width; + textBoxHeight = box.size.height; + + // top of text box + double textBoxAbsY = box.localToGlobal(Offset.zero).dy; + + // height of window + double windowHeight = MediaQuery.of(context).size.height; + + // we need to find the root MediaQuery for the unsafe area height + // we cannot use BuildContext.ancestorWidgetOfExactType because + // widgets like SafeArea creates a new MediaQuery with the padding removed + MediaQuery rootMediaQuery = _findRootMediaQuery()!; + + // height of keyboard + double keyboardHeight = rootMediaQuery.data.viewInsets.bottom; + + double maxHDesired = _calculateMaxHeight(desiredDirection, box, widget, + windowHeight, rootMediaQuery, keyboardHeight, textBoxAbsY); + + // if there's enough room in the desired direction, update the direction and the max height + if (maxHDesired >= minOverlaySpace || !autoFlipDirection) { + direction = desiredDirection; + // Sometimes textBoxAbsY is NaN, so we need to check for that + if(!maxHDesired.isNaN) { + maxHeight = maxHDesired; + } + } else { + // There's not enough room in the desired direction so see how much room is in the opposite direction + AxisDirection flipped = flipAxisDirection(desiredDirection); + double maxHFlipped = _calculateMaxHeight(flipped, box, widget, + windowHeight, rootMediaQuery, keyboardHeight, textBoxAbsY); + + // if there's more room in this opposite direction, update the direction and maxHeight + if (maxHFlipped > maxHDesired) { + direction = flipped; + + // Not sure if this is needed, but it's here just in case + if(!maxHFlipped.isNaN) { + maxHeight = maxHFlipped; + } + } + } + + if (maxHeight < 0) maxHeight = 0; + } + + double _calculateMaxHeight( + AxisDirection direction, + RenderBox box, + TypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + return direction == AxisDirection.down + ? _calculateMaxHeightDown(box, widget, windowHeight, rootMediaQuery, + keyboardHeight, textBoxAbsY) + : _calculateMaxHeightUp(box, widget, windowHeight, rootMediaQuery, + keyboardHeight, textBoxAbsY); + } + + double _calculateMaxHeightDown( + RenderBox box, + TypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + // unsafe area, ie: iPhone X 'home button' + // keyboardHeight includes unsafeAreaHeight, if keyboard is showing, set to 0 + double unsafeAreaHeight = + keyboardHeight == 0 ? rootMediaQuery.data.padding.bottom : 0; + + return windowHeight - + keyboardHeight - + unsafeAreaHeight - + textBoxHeight - + textBoxAbsY - + 2 * widget.suggestionsBoxVerticalOffset; + } + + double _calculateMaxHeightUp( + RenderBox box, + TypeAheadField widget, + double windowHeight, + MediaQuery rootMediaQuery, + double keyboardHeight, + double textBoxAbsY) { + // recalculate keyboard absolute y value + double keyboardAbsY = windowHeight - keyboardHeight; + + directionUpOffset = textBoxAbsY > keyboardAbsY + ? keyboardAbsY - textBoxAbsY - widget.suggestionsBoxVerticalOffset + : -widget.suggestionsBoxVerticalOffset; + + // unsafe area, ie: iPhone X notch + double unsafeAreaHeight = rootMediaQuery.data.padding.top; + + return textBoxAbsY > keyboardAbsY + ? keyboardAbsY - + unsafeAreaHeight - + 2 * widget.suggestionsBoxVerticalOffset + : textBoxAbsY - + unsafeAreaHeight - + 2 * widget.suggestionsBoxVerticalOffset; + } + + Future onChangeMetrics() async { + if (await _waitChangeMetrics()) { + resize(); + } + } +} \ No newline at end of file diff --git a/lib/src/material/suggestions_box/suggestions_box_controller.dart b/lib/src/material/suggestions_box/suggestions_box_controller.dart new file mode 100644 index 0000000..853328d --- /dev/null +++ b/lib/src/material/suggestions_box/suggestions_box_controller.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box.dart'; + +/// Supply an instance of this class to the [TypeAhead.suggestionsBoxController] +/// property to manually control the suggestions box +class SuggestionsBoxController { + SuggestionsBox? suggestionsBox; + FocusNode? effectiveFocusNode; + + /// Opens the suggestions box + void open() { + effectiveFocusNode?.requestFocus(); + } + + bool isOpened() { + return suggestionsBox?.isOpened ?? false; + } + + /// Closes the suggestions box + void close() { + effectiveFocusNode?.unfocus(); + } + + /// Opens the suggestions box if closed and vice-versa + void toggle() { + if (suggestionsBox?.isOpened ?? false) { + close(); + } else { + open(); + } + } + + /// Recalculates the height of the suggestions box + void resize() { + suggestionsBox!.resize(); + } +} \ No newline at end of file diff --git a/lib/src/material/suggestions_box/suggestions_box_decoration.dart b/lib/src/material/suggestions_box/suggestions_box_decoration.dart new file mode 100644 index 0000000..4f618ff --- /dev/null +++ b/lib/src/material/suggestions_box/suggestions_box_decoration.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +/// Supply an instance of this class to the [TypeAhead.suggestionsBoxDecoration] +/// property to configure the suggestions box decoration +class SuggestionsBoxDecoration { + /// The z-coordinate at which to place the suggestions box. This controls the size + /// of the shadow below the box. + /// + /// Same as [Material.elevation](https://docs.flutter.io/flutter/material/Material/elevation.html) + final double elevation; + + /// The color to paint the suggestions box. + /// + /// Same as [Material.color](https://docs.flutter.io/flutter/material/Material/color.html) + final Color? color; + + /// Defines the material's shape as well its shadow. + /// + /// Same as [Material.shape](https://docs.flutter.io/flutter/material/Material/shape.html) + final ShapeBorder? shape; + + /// Defines if a scrollbar will be displayed or not. + final bool hasScrollbar; + + /// If non-null, the corners of this box are rounded by this [BorderRadius](https://docs.flutter.io/flutter/painting/BorderRadius-class.html). + /// + /// Same as [Material.borderRadius](https://docs.flutter.io/flutter/material/Material/borderRadius.html) + final BorderRadius? borderRadius; + + /// The color to paint the shadow below the material. + /// + /// Same as [Material.shadowColor](https://docs.flutter.io/flutter/material/Material/shadowColor.html) + final Color shadowColor; + + /// The constraints to be applied to the suggestions box + final BoxConstraints? constraints; + + /// Adds an offset to the suggestions box + final double offsetX; + + /// The content will be clipped (or not) according to this option. + /// + /// Same as [Material.clipBehavior](https://api.flutter.dev/flutter/material/Material/clipBehavior.html) + final Clip clipBehavior; + + /// Creates a SuggestionsBoxDecoration + const SuggestionsBoxDecoration( + {this.elevation = 4.0, + this.color, + this.shape, + this.hasScrollbar = true, + this.borderRadius, + this.shadowColor = const Color(0xFF000000), + this.constraints, + this.clipBehavior = Clip.none, + this.offsetX = 0.0}); +} \ No newline at end of file diff --git a/lib/src/material/suggestions_box/suggestions_list.dart b/lib/src/material/suggestions_box/suggestions_list.dart new file mode 100644 index 0000000..e6ff350 --- /dev/null +++ b/lib/src/material/suggestions_box/suggestions_list.dart @@ -0,0 +1,411 @@ +import 'dart:async'; +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_typeahead/src/keyboard_suggestion_selection_notifier.dart'; +import 'package:flutter_typeahead/src/should_refresh_suggestion_focus_index_notifier.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box.dart'; +import 'package:flutter_typeahead/src/material/suggestions_box/suggestions_box_decoration.dart'; +import 'package:flutter_typeahead/src/typedef.dart'; + +class SuggestionsList extends StatefulWidget { + final SuggestionsBox? suggestionsBox; + final TextEditingController? controller; + final bool getImmediateSuggestions; + final SuggestionSelectionCallback? onSuggestionSelected; + final SuggestionsCallback? suggestionsCallback; + final ItemBuilder? itemBuilder; + final ScrollController? scrollController; + final SuggestionsBoxDecoration? decoration; + final Duration? debounceDuration; + final WidgetBuilder? loadingBuilder; + final WidgetBuilder? noItemsFoundBuilder; + final ErrorBuilder? errorBuilder; + final AnimationTransitionBuilder? transitionBuilder; + final Duration? animationDuration; + final double? animationStart; + final AxisDirection? direction; + final bool? hideOnLoading; + final bool? hideOnEmpty; + final bool? hideOnError; + final bool? keepSuggestionsOnLoading; + final int? minCharsForSuggestions; + final KeyboardSuggestionSelectionNotifier keyboardSuggestionSelectionNotifier; + final ShouldRefreshSuggestionFocusIndexNotifier + shouldRefreshSuggestionFocusIndexNotifier; + final VoidCallback giveTextFieldFocus; + final VoidCallback onSuggestionFocus; + final KeyEventResult Function(FocusNode _, RawKeyEvent event) onKeyEvent; + final bool hideKeyboardOnDrag; + + SuggestionsList({ + required this.suggestionsBox, + this.controller, + this.getImmediateSuggestions = false, + this.onSuggestionSelected, + this.suggestionsCallback, + this.itemBuilder, + this.scrollController, + this.decoration, + this.debounceDuration, + this.loadingBuilder, + this.noItemsFoundBuilder, + this.errorBuilder, + this.transitionBuilder, + this.animationDuration, + this.animationStart, + this.direction, + this.hideOnLoading, + this.hideOnEmpty, + this.hideOnError, + this.keepSuggestionsOnLoading, + this.minCharsForSuggestions, + required this.keyboardSuggestionSelectionNotifier, + required this.shouldRefreshSuggestionFocusIndexNotifier, + required this.giveTextFieldFocus, + required this.onSuggestionFocus, + required this.onKeyEvent, + required this.hideKeyboardOnDrag, + }); + + @override + _SuggestionsListState createState() => _SuggestionsListState(); +} + +class _SuggestionsListState extends State> + with SingleTickerProviderStateMixin { + Iterable? _suggestions; + late bool _suggestionsValid; + late VoidCallback _controllerListener; + Timer? _debounceTimer; + bool? _isLoading, _isQueued; + Object? _error; + AnimationController? _animationController; + String? _lastTextValue; + late final ScrollController _scrollController = + widget.scrollController ?? ScrollController(); + List _focusNodes = []; + int _suggestionIndex = -1; + + _SuggestionsListState() { + this._controllerListener = () { + // If we came here because of a change in selected text, not because of + // actual change in text + if (widget.controller!.text == this._lastTextValue) return; + + this._lastTextValue = widget.controller!.text; + + this._debounceTimer?.cancel(); + if (widget.controller!.text.length < widget.minCharsForSuggestions!) { + if (mounted) { + setState(() { + _isLoading = false; + _suggestions = null; + _suggestionsValid = true; + }); + } + return; + } else { + this._debounceTimer = Timer(widget.debounceDuration!, () async { + if (this._debounceTimer!.isActive) return; + if (_isLoading!) { + _isQueued = true; + return; + } + + await this.invalidateSuggestions(); + while (_isQueued!) { + _isQueued = false; + await this.invalidateSuggestions(); + } + }); + } + }; + } + + @override + void didUpdateWidget(SuggestionsList oldWidget) { + super.didUpdateWidget(oldWidget); + widget.controller!.addListener(this._controllerListener); + _getSuggestions(); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _getSuggestions(); + } + + @override + void initState() { + super.initState(); + + this._animationController = AnimationController( + vsync: this, + duration: widget.animationDuration, + ); + + this._suggestionsValid = widget.minCharsForSuggestions! > 0 ? true : false; + this._isLoading = false; + this._isQueued = false; + this._lastTextValue = widget.controller!.text; + + if (widget.getImmediateSuggestions) { + this._getSuggestions(); + } + + widget.controller!.addListener(this._controllerListener); + + widget.keyboardSuggestionSelectionNotifier.addListener(() { + final suggestionsLength = _suggestions?.length; + final event = widget.keyboardSuggestionSelectionNotifier.value; + if (event == null || suggestionsLength == null) return; + + if (event == LogicalKeyboardKey.arrowDown && + _suggestionIndex < suggestionsLength - 1) { + _suggestionIndex++; + } else if (event == LogicalKeyboardKey.arrowUp && _suggestionIndex > -1) { + _suggestionIndex--; + } + + if (_suggestionIndex > -1 && _suggestionIndex < _focusNodes.length) { + final focusNode = _focusNodes[_suggestionIndex]; + focusNode.requestFocus(); + widget.onSuggestionFocus(); + } else { + widget.giveTextFieldFocus(); + } + }); + + widget.shouldRefreshSuggestionFocusIndexNotifier.addListener(() { + if (_suggestionIndex != -1) { + _suggestionIndex = -1; + } + }); + } + + Future invalidateSuggestions() async { + _suggestionsValid = false; + await _getSuggestions(); + } + + Future _getSuggestions() async { + if (_suggestionsValid) return; + _suggestionsValid = true; + + if (mounted) { + setState(() { + this._animationController!.forward(from: 1.0); + + this._isLoading = true; + this._error = null; + }); + + Iterable? suggestions; + Object? error; + + try { + suggestions = + await widget.suggestionsCallback!(widget.controller!.text); + } catch (e) { + error = e; + } + + if (this.mounted) { + // if it wasn't removed in the meantime + setState(() { + double? animationStart = widget.animationStart; + // allow suggestionsCallback to return null and not throw error here + if (error != null || suggestions?.isEmpty == true) { + animationStart = 1.0; + } + this._animationController!.forward(from: animationStart); + + this._error = error; + this._isLoading = false; + this._suggestions = suggestions; + _focusNodes = List.generate( + _suggestions?.length ?? 0, + (index) => FocusNode(onKey: (_, event) { + return widget.onKeyEvent(_, event); + }), + ); + }); + } + } + } + + @override + void dispose() { + _animationController!.dispose(); + _debounceTimer?.cancel(); + for (final focusNode in _focusNodes) { + focusNode.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool isEmpty = + this._suggestions?.length == 0 && widget.controller!.text == ""; + if ((this._suggestions == null || isEmpty) && + this._isLoading == false && + this._error == null) return Container(); + + Widget child; + if (this._isLoading!) { + if (widget.hideOnLoading!) { + child = Container(height: 0); + } else { + child = createLoadingWidget(); + } + } else if (this._error != null) { + if (widget.hideOnError!) { + child = Container(height: 0); + } else { + child = createErrorWidget(); + } + } else if (this._suggestions!.isEmpty) { + if (widget.hideOnEmpty!) { + child = Container(height: 0); + } else { + child = createNoItemsFoundWidget(); + } + } else { + child = createSuggestionsWidget(); + } + + final animationChild = widget.transitionBuilder != null + ? widget.transitionBuilder!(context, child, this._animationController) + : SizeTransition( + axisAlignment: -1.0, + sizeFactor: CurvedAnimation( + parent: this._animationController!, + curve: Curves.fastOutSlowIn), + child: child, + ); + + BoxConstraints constraints; + if (widget.decoration!.constraints == null) { + constraints = BoxConstraints( + maxHeight: widget.suggestionsBox!.maxHeight, + ); + } else { + double maxHeight = min(widget.decoration!.constraints!.maxHeight, + widget.suggestionsBox!.maxHeight); + constraints = widget.decoration!.constraints!.copyWith( + minHeight: min(widget.decoration!.constraints!.minHeight, maxHeight), + maxHeight: maxHeight, + ); + } + + var container = Material( + elevation: widget.decoration!.elevation, + color: widget.decoration!.color, + shape: widget.decoration!.shape, + borderRadius: widget.decoration!.borderRadius, + shadowColor: widget.decoration!.shadowColor, + clipBehavior: widget.decoration!.clipBehavior, + child: ConstrainedBox( + constraints: constraints, + child: animationChild, + ), + ); + + return container; + } + + Widget createLoadingWidget() { + Widget child; + + if (widget.keepSuggestionsOnLoading! && this._suggestions != null) { + if (this._suggestions!.isEmpty) { + child = createNoItemsFoundWidget(); + } else { + child = createSuggestionsWidget(); + } + } else { + child = widget.loadingBuilder != null + ? widget.loadingBuilder!(context) + : Align( + alignment: Alignment.center, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: CircularProgressIndicator(), + ), + ); + } + + return child; + } + + Widget createErrorWidget() { + return widget.errorBuilder != null + ? widget.errorBuilder!(context, this._error) + : Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Error: ${this._error}', + style: TextStyle(color: Theme.of(context).colorScheme.error), + ), + ); + } + + Widget createNoItemsFoundWidget() { + return widget.noItemsFoundBuilder != null + ? widget.noItemsFoundBuilder!(context) + : Padding( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: Text( + 'No Items Found!', + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).disabledColor, fontSize: 18.0), + ), + ); + } + + Widget createSuggestionsWidget() { + Widget child = ListView( + padding: EdgeInsets.zero, + primary: false, + shrinkWrap: true, + keyboardDismissBehavior: widget.hideKeyboardOnDrag + ? ScrollViewKeyboardDismissBehavior.onDrag + : ScrollViewKeyboardDismissBehavior.manual, + controller: _scrollController, + reverse: widget.suggestionsBox!.direction == AxisDirection.down + ? false + : widget.suggestionsBox!.autoFlipListDirection, + children: List.generate(this._suggestions!.length, (index) { + final suggestion = _suggestions!.elementAt(index); + final focusNode = _focusNodes[index]; + + return TextFieldTapRegion( + child: InkWell( + focusColor: Theme.of(context).hoverColor, + focusNode: focusNode, + child: widget.itemBuilder!(context, suggestion), + onTap: () { + // * we give the focus back to the text field + widget.giveTextFieldFocus(); + + widget.onSuggestionSelected!(suggestion); + }, + ), + ); + }), + ); + + if (widget.decoration!.hasScrollbar) { + child = Scrollbar( + controller: _scrollController, + child: child, + ); + } + + return child; + } +} \ No newline at end of file diff --git a/lib/src/should_refresh_suggestion_focus_index_notifier.dart b/lib/src/should_refresh_suggestion_focus_index_notifier.dart new file mode 100644 index 0000000..dedd74f --- /dev/null +++ b/lib/src/should_refresh_suggestion_focus_index_notifier.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; + +class ShouldRefreshSuggestionFocusIndexNotifier extends ValueNotifier { + ShouldRefreshSuggestionFocusIndexNotifier( + {required FocusNode? textFieldFocusNode}) + : super(null) { + textFieldFocusNode?.addListener(() { + if (textFieldFocusNode.hasFocus) { + notifyListeners(); + } + }); + } +} diff --git a/lib/src/typedef.dart b/lib/src/typedef.dart new file mode 100644 index 0000000..79b11de --- /dev/null +++ b/lib/src/typedef.dart @@ -0,0 +1,11 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; + +typedef FutureOr> SuggestionsCallback(String pattern); +typedef Widget ItemBuilder(BuildContext context, T itemData); +typedef void SuggestionSelectionCallback(T suggestion); +typedef Widget ErrorBuilder(BuildContext context, Object? error); + +typedef Widget AnimationTransitionBuilder( + BuildContext context, Widget child, AnimationController? controller); diff --git a/lib/src/utils.dart b/lib/src/utils.dart new file mode 100644 index 0000000..f8a3062 --- /dev/null +++ b/lib/src/utils.dart @@ -0,0 +1,5 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; + +final supportedPlatform = (kIsWeb || Platform.isAndroid || Platform.isIOS); diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..4f695d1 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,51 @@ +name: flutter_typeahead +version: 4.3.7 + +description: A highly customizable typeahead (autocomplete) text input field for Flutter +homepage: https://github.com/AbdulRahmanAlHamali/flutter_typeahead + +dependencies: + flutter: + sdk: flutter + flutter_keyboard_visibility: ^6.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter +environment: + sdk: '>=2.19.0 <3.0.0' + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: +# To add assets to your package, add an assets section, like this: +# assets: +# - images/a_dot_burr.jpeg +# - images/a_dot_ham.jpeg +# +# For details regarding assets in packages, see +# https://flutter.io/assets-and-images/#from-packages +# +# An image asset can refer to one or more resolution-specific "variants", see +# https://flutter.io/assets-and-images/#resolution-aware. +# To add custom fonts to your package, add a fonts section here, +# in this "flutter" section. Each entry in this list should have a +# "family" key with the font family name, and a "fonts" key with a +# list giving the asset and other descriptors for the font. For +# example: +# fonts: +# - family: Schyler +# fonts: +# - asset: fonts/Schyler-Regular.ttf +# - asset: fonts/Schyler-Italic.ttf +# style: italic +# - family: Trajan Pro +# fonts: +# - asset: fonts/TrajanPro.ttf +# - asset: fonts/TrajanPro_Bold.ttf +# weight: 700 +# +# For details regarding fonts in packages, see +# https://flutter.io/custom-fonts/#from-packages diff --git a/scripts/code_analysis.sh b/scripts/code_analysis.sh new file mode 100644 index 0000000..b7d6362 --- /dev/null +++ b/scripts/code_analysis.sh @@ -0,0 +1,9 @@ +cd .. +echo "> # Library code # lib:" +find ./lib -name "*.dart" -type f|xargs wc -l | grep total +echo"> How the library code is distributed between files:" +find ./lib -name "*.dart" -type f|xargs wc -l +echo "> # Example:" +find ./example/lib -name "*.dart" -type f|xargs wc -l | grep main +echo "> # Should have nothing after this line, as examples are single files in pub.dev" +find ./example/lib -name "*.dart" -type f|xargs wc -l | grep total diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100644 index 0000000..307ea39 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,2 @@ +cd .. +dart pub publish \ No newline at end of file diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh new file mode 100644 index 0000000..e8d808b --- /dev/null +++ b/scripts/run_tests.sh @@ -0,0 +1,2 @@ +cd .. +flutter test \ No newline at end of file diff --git a/test/flutter_typeahead_test.dart b/test/flutter_typeahead_test.dart new file mode 100644 index 0000000..4cc88cb --- /dev/null +++ b/test/flutter_typeahead_test.dart @@ -0,0 +1,254 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_typeahead/flutter_typeahead.dart'; + +class TestPage extends StatefulWidget { + final int minCharsForSuggestions; + TestPage({Key? key, this.minCharsForSuggestions = 0}) : super(key: key); + + @override + State createState() => TestPageState(); +} + +class TestPageState extends State { + final _formKey = GlobalKey(); + final TextEditingController _controller = TextEditingController(); + + @override + void initState() { + super.initState(); + _controller.text = 'Default text'; + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Test'), + ), + // https://medium.com/flutterpub/create-beautiful-forms-with-flutter-47075cfe712 + body: Form( + key: _formKey, + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 16.0), + children: [ + TypeAheadFormField( + textFieldConfiguration: TextFieldConfiguration( + autofocus: true, + inputFormatters: [LengthLimitingTextInputFormatter(50)], + controller: _controller, + decoration: InputDecoration(labelText: 'Type Ahead')), + suggestionsCallback: (pattern) { + if (pattern.length > 0) + return [pattern + 'aaa', pattern + 'bbb']; + else + return []; + }, + noItemsFoundBuilder: (context) => const SizedBox(), + itemBuilder: (context, String suggestion) { + return ListTile( + title: Text(suggestion), + ); + }, + onSuggestionSelected: (String suggestion) => + this._controller.text = suggestion, + minCharsForSuggestions: widget.minCharsForSuggestions, + ), + ], + ), + )); + } +} + +class CupertinoTestPage extends StatefulWidget { + final int minCharsForSuggestions; + CupertinoTestPage({Key? key, this.minCharsForSuggestions = 0}) + : super(key: key); + + @override + State createState() => CupertinoTestPageState(); +} + +class CupertinoTestPageState extends State { + final _formKey = GlobalKey(); + final TextEditingController _controller = TextEditingController(); + + @override + void initState() { + super.initState(); + _controller.text = 'Default text'; + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Test'), + ), + // https://medium.com/flutterpub/create-beautiful-forms-with-flutter-47075cfe712 + body: Form( + key: _formKey, + child: ListView( + padding: EdgeInsets.symmetric(horizontal: 16.0), + children: [ + CupertinoTypeAheadFormField( + textFieldConfiguration: CupertinoTextFieldConfiguration( + autofocus: true, + inputFormatters: [LengthLimitingTextInputFormatter(50)], + controller: _controller, + ), + suggestionsCallback: (pattern) { + if (pattern.length > 0) + return [pattern + 'aaa', pattern + 'bbb']; + else + return []; + }, + noItemsFoundBuilder: (context) => const SizedBox(), + itemBuilder: (context, String suggestion) { + return Text(suggestion); + }, + onSuggestionSelected: (String suggestion) => + this._controller.text = suggestion, + minCharsForSuggestions: widget.minCharsForSuggestions), + ], + ), + )); + } +} + +void main() { + group('TypeAheadFormField', () { + testWidgets('load and dispose', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: TestPage())); + await tester.pumpAndSettle(); + + expect(find.text('Type Ahead'), findsOneWidget); + expect(find.text('Default text'), findsOneWidget); + }); + testWidgets('text input', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: TestPage())); + await tester.pumpAndSettle(); + + // Not using tester.enterText because the text input should already be focused. + tester.testTextInput.enterText("test"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("testaaa"), findsOneWidget); + expect(find.text("testbbb"), findsOneWidget); + tester.testTextInput.enterText("test2"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("testaaa"), findsNothing); + expect(find.text("testbbb"), findsNothing); + expect(find.text("test2aaa"), findsOneWidget); + expect(find.text("test2bbb"), findsOneWidget); + }); + + testWidgets('min chars for suggestions', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: TestPage( + minCharsForSuggestions: 4, + ))); + await tester.pumpAndSettle(); + + tester.testTextInput.enterText("333"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("333aaa"), findsNothing); + expect(find.text("333bbb"), findsNothing); + tester.testTextInput.enterText("4444"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("4444aaa"), findsOneWidget); + expect(find.text("4444bbb"), findsOneWidget); + }); + // testWidgets('entering text works', (WidgetTester tester) async { + // await tester.pumpWidget(MaterialApp(home: TestPage())); + // await tester.pumpAndSettle(); + // await tester.enterText(find.byType(TypeAheadFormField), 'new text'); + // }); + + // Up/down keyboard tests have been commented out due to a PR that + // doesn't track them anymore to fix another bug .. sort of odd + // testWidgets('handle key up/down events', (WidgetTester tester) async { + // await tester.pumpWidget(MaterialApp(home: TestPage())); + // await tester.pumpAndSettle(); + + // tester.testTextInput.enterText("keyTest"); + // await tester.pumpAndSettle(Duration(milliseconds: 2000)); + + // final textFieldFinder = find.byKey(TestKeys.textFieldKey); + // final TextField textField = tester.firstWidget(textFieldFinder); + + // final firstSuggestionText = find.text("keyTestaaa"); + // final firstSuggestionWrapperFinder = find.ancestor( + // of: firstSuggestionText, + // matching: find.byKey(TestKeys.getSuggestionKey(0))); + // final InkWell firstSuggestion = + // tester.firstWidget(firstSuggestionWrapperFinder); + + // expect(textFieldFinder, findsOneWidget); + + // expect(firstSuggestionText, findsOneWidget); + // expect(firstSuggestionWrapperFinder, findsOneWidget); + + // expect(textField.focusNode?.hasFocus, true); + // expect(firstSuggestion.focusNode?.hasFocus, false); + + // await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); + + // expect(textField.focusNode?.hasFocus, false); + // expect(firstSuggestion.focusNode?.hasFocus, true); + // }); + }); + group('CupertinoTypeAheadFormField', () { + testWidgets('load and dispose', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: CupertinoTestPage())); + await tester.pumpAndSettle(); + + expect(find.text('Default text'), findsOneWidget); + }); + testWidgets('text input', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp(home: CupertinoTestPage())); + await tester.pumpAndSettle(); + + // Not using tester.enterText because the text input should already be focused. + tester.testTextInput.enterText("test"); + await tester.pump(Duration(milliseconds: 2000)); + expect(find.text("testaaa"), findsOneWidget); + expect(find.text("testbbb"), findsOneWidget); + tester.testTextInput.enterText("test2"); + await tester.pump(Duration(milliseconds: 2000)); + expect(find.text("testaaa"), findsNothing); + expect(find.text("testbbb"), findsNothing); + expect(find.text("test2aaa"), findsOneWidget); + expect(find.text("test2bbb"), findsOneWidget); + }); + + testWidgets('min chars for suggestions', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + home: TestPage( + minCharsForSuggestions: 4, + ))); + await tester.pumpAndSettle(); + + tester.testTextInput.enterText("333"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("333aaa"), findsNothing); + expect(find.text("333bbb"), findsNothing); + tester.testTextInput.enterText("4444"); + await tester.pumpAndSettle(Duration(milliseconds: 2000)); + expect(find.text("4444aaa"), findsOneWidget); + expect(find.text("4444bbb"), findsOneWidget); + }); + }); +}