├── example ├── linux │ ├── .gitignore │ ├── main.cc │ ├── flutter │ │ ├── generated_plugin_registrant.cc │ │ ├── generated_plugin_registrant.h │ │ ├── generated_plugins.cmake │ │ └── CMakeLists.txt │ ├── my_application.h │ ├── my_application.cc │ └── CMakeLists.txt ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcshareddata │ │ │ └── xcschemes │ │ │ │ └── Runner.xcscheme │ │ └── project.pbxproj │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── .gitignore ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ └── Icon-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── example │ │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── analysis_options.yaml ├── pubspec.yaml ├── test │ └── widget_test.dart ├── README.md ├── lib │ ├── submenu_card.dart │ ├── main.dart │ └── main_more.dart ├── .gitignore ├── .metadata └── pubspec.lock ├── images ├── panel.png ├── semiL.png ├── semiR.png ├── circle.png ├── linear.png ├── semiUp.png ├── dropdown.png ├── semiDown.png ├── StarMenuDemo.gif ├── quarterTopL.png ├── quarterTopR.png ├── StarMenuDemo2.gif ├── StarMenuDemo2.mp4 ├── quarterBottomL.png ├── quarterBottomR.png └── dont_buy_me_coffe.png ├── analysis_options.yaml ├── test └── star_menu_test.dart ├── .idea ├── markdown-navigator │ └── profiles_settings.xml ├── vcs.xml ├── libraries │ ├── Flutter_Plugins.xml │ ├── Dart_SDK.xml │ └── Dart_Packages.xml ├── modules.xml ├── markdown-navigator.xml └── workspace.xml ├── .vscode ├── settings.json └── launch.json ├── .metadata ├── lib ├── star_menu.dart └── src │ ├── center_widget.dart │ ├── params │ ├── grid_shape_params.dart │ ├── linear_shape_params.dart │ ├── circle_shape_params.dart │ ├── boundary_background.dart │ ├── background_params.dart │ └── star_menu_params.dart │ ├── widget_params.dart │ ├── dinamyc_star_menu.dart │ └── star_item.dart ├── pubspec.yaml ├── LICENSE ├── star_menu.iml ├── .gitignore ├── CHANGELOG.md ├── pubspec.lock └── README.md /example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /images/panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/panel.png -------------------------------------------------------------------------------- /images/semiL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/semiL.png -------------------------------------------------------------------------------- /images/semiR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/semiR.png -------------------------------------------------------------------------------- /images/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/circle.png -------------------------------------------------------------------------------- /images/linear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/linear.png -------------------------------------------------------------------------------- /images/semiUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/semiUp.png -------------------------------------------------------------------------------- /images/dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/dropdown.png -------------------------------------------------------------------------------- /images/semiDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/semiDown.png -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /images/StarMenuDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/StarMenuDemo.gif -------------------------------------------------------------------------------- /images/quarterTopL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/quarterTopL.png -------------------------------------------------------------------------------- /images/quarterTopR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/quarterTopR.png -------------------------------------------------------------------------------- /images/StarMenuDemo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/StarMenuDemo2.gif -------------------------------------------------------------------------------- /images/StarMenuDemo2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/StarMenuDemo2.mp4 -------------------------------------------------------------------------------- /images/quarterBottomL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/quarterBottomL.png -------------------------------------------------------------------------------- /images/quarterBottomR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/quarterBottomR.png -------------------------------------------------------------------------------- /images/dont_buy_me_coffe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/images/dont_buy_me_coffe.png -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false -------------------------------------------------------------------------------- /test/star_menu_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | test('adds one to input values', () {}); 5 | } 6 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:very_good_analysis/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | public_member_api_docs: false 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alnitak/flutter_star_menu/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.configureOnOpen": false, 3 | "cmake.sourceDirectory": "/home/deimos/FLUTTER/selenium4/libs/star_menu/example/linux", 4 | "dart.showMainCodeLens": true, 5 | "java.compile.nullAnalysis.mode": "disabled" 6 | } -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | 10 | void fl_register_plugins(FlPluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8661d8aecd626f7f57ccbcb735553edc05a2e713 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /lib/star_menu.dart: -------------------------------------------------------------------------------- 1 | library star_menu; 2 | 3 | export 'src/dinamyc_star_menu.dart'; 4 | export 'src/params/background_params.dart'; 5 | export 'src/params/boundary_background.dart'; 6 | export 'src/params/circle_shape_params.dart'; 7 | export 'src/params/grid_shape_params.dart'; 8 | export 'src/params/linear_shape_params.dart'; 9 | export 'src/params/star_menu_params.dart'; 10 | export 'src/star_menu.dart'; 11 | -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | project.evaluationDependsOn(':app') 14 | } 15 | 16 | tasks.register("clean", Delete) { 17 | delete rootProject.buildDir 18 | } 19 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/src/center_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/widgets.dart'; 2 | 3 | class CenteredWidget extends StatelessWidget { 4 | const CenteredWidget({ 5 | required this.child, 6 | super.key, 7 | }); 8 | 9 | final Widget child; 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return FractionalTranslation( 14 | translation: const Offset(-0.5, -0.5), 15 | child: child, 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: star_menu_example 2 | description: StarMenu contextual pop up menu demo. 3 | publish_to: 'none' 4 | homepage: www.marcobavagnoli.com 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: '>=3.2.0 <4.0.0' 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | star_menu: 16 | path: ../ 17 | 18 | cupertino_icons: ^1.0.6 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | very_good_analysis: ^5.1.0 25 | 26 | flutter: 27 | 28 | uses-material-design: true 29 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter_test/flutter_test.dart'; 9 | 10 | void main() { 11 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {}); 12 | } 13 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # star_menu_example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/lib/submenu_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SubMenuCard extends StatelessWidget { 4 | const SubMenuCard({ 5 | required this.width, 6 | super.key, 7 | this.text = '', 8 | }); 9 | final double width; 10 | final String text; 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Card( 15 | elevation: 8, 16 | child: Padding( 17 | padding: const EdgeInsets.all(8), 18 | child: SizedBox( 19 | width: width, 20 | child: Text(text, textAlign: TextAlign.center), 21 | ), 22 | ), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: star_menu 2 | description: Contextual popup menu with different shapes and multiple ways to fine-tune animation and position. The menu entries can be almost any kind of widgets. 3 | version: 4.0.1 4 | homepage: https://github.com/alnitak/flutter_star_menu 5 | issue_tracker: https://github.com/alnitak/flutter_star_menu/issues 6 | repository: https://github.com/alnitak/flutter_star_menu 7 | 8 | environment: 9 | sdk: '>=3.2.0 <4.0.0' 10 | flutter: ">=1.17.0" 11 | 12 | dependencies: 13 | flutter: 14 | sdk: flutter 15 | 16 | vector_math: ^2.1.4 17 | 18 | dev_dependencies: 19 | flutter_test: 20 | sdk: flutter 21 | 22 | very_good_analysis: ^5.1.0 23 | 24 | flutter: 25 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "star_menu_example", 3 | "short_name": "star_menu_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/ephemeral/ 22 | Flutter/app.flx 23 | Flutter/app.zip 24 | Flutter/flutter_assets/ 25 | Flutter/flutter_export_environment.sh 26 | ServiceDefinitions.json 27 | Runner/GeneratedPluginRegistrant.* 28 | 29 | # Exceptions to above rules. 30 | !default.mode1v3 31 | !default.mode2v3 32 | !default.pbxuser 33 | !default.perspectivev3 34 | -------------------------------------------------------------------------------- /lib/src/params/grid_shape_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// class to define grid shape params 4 | @immutable 5 | class GridShapeParams { 6 | const GridShapeParams({ 7 | this.columns = 3, 8 | this.columnsSpaceH = 0, 9 | this.columnsSpaceV = 0, 10 | }); 11 | 12 | /// Number of columns 13 | final int columns; 14 | 15 | /// Horizontal space between items 16 | final int columnsSpaceH; 17 | 18 | /// Vertical space between items 19 | final int columnsSpaceV; 20 | 21 | GridShapeParams copyWith({ 22 | int? columns, 23 | int? columnsSpaceH, 24 | int? columnsSpaceV, 25 | }) { 26 | return GridShapeParams( 27 | columns: columns ?? this.columns, 28 | columnsSpaceH: columnsSpaceH ?? this.columnsSpaceH, 29 | columnsSpaceV: columnsSpaceV ?? this.columnsSpaceV, 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | ) 7 | 8 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 9 | ) 10 | 11 | set(PLUGIN_BUNDLED_LIBRARIES) 12 | 13 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 14 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 15 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 16 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 18 | endforeach(plugin) 19 | 20 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 21 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | } 9 | settings.ext.flutterSdkPath = flutterSdkPath() 10 | 11 | includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") 12 | 13 | repositories { 14 | google() 15 | mavenCentral() 16 | gradlePluginPortal() 17 | } 18 | } 19 | 20 | plugins { 21 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 22 | id "com.android.application" version "7.3.0" apply false 23 | id "org.jetbrains.kotlin.android" version "1.7.10" apply false 24 | } 25 | 26 | include ":app" 27 | -------------------------------------------------------------------------------- /lib/src/params/linear_shape_params.dart: -------------------------------------------------------------------------------- 1 | enum LinearAlignment { left, center, right, top, bottom } 2 | 3 | /// class to define linear shape params 4 | class LinearShapeParams { 5 | const LinearShapeParams({ 6 | this.angle = 90, 7 | this.space = 0, 8 | this.alignment = LinearAlignment.center, 9 | }); 10 | 11 | /// Degree angle. Anticlockwise with 0° on 3 o'clock 12 | final double angle; 13 | 14 | /// Space between items 15 | final double space; 16 | 17 | /// left, center, right, top, bottom. Useful when the linear shape 18 | /// is vertical or horizontal 19 | final LinearAlignment alignment; 20 | 21 | LinearShapeParams copyWith({ 22 | double? angle, 23 | double? space, 24 | LinearAlignment? alignment, 25 | }) { 26 | return LinearShapeParams( 27 | angle: angle ?? this.angle, 28 | space: space ?? this.space, 29 | alignment: alignment ?? this.alignment, 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/params/circle_shape_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// class to define circle shape params 4 | @immutable 5 | class CircleShapeParams { 6 | const CircleShapeParams({ 7 | this.radiusX = 100, 8 | this.radiusY = 100, 9 | this.startAngle = 0, 10 | this.endAngle = 360, 11 | }); 12 | 13 | /// Horizontal radius 14 | final double radiusX; 15 | 16 | /// Vertical radius 17 | final double radiusY; 18 | 19 | /// Starting angle for the 1st item. Anticlockwise with 0° on the right 20 | final double startAngle; 21 | 22 | /// Ending angle for the 1st item. Anticlockwise with 0° on the right 23 | final double endAngle; 24 | 25 | CircleShapeParams copyWith({ 26 | double? radiusX, 27 | double? radiusY, 28 | double? startAngle, 29 | double? endAngle, 30 | }) { 31 | return CircleShapeParams( 32 | radiusX: radiusX ?? this.radiusX, 33 | radiusY: radiusY ?? this.radiusY, 34 | startAngle: startAngle ?? this.startAngle, 35 | endAngle: endAngle ?? this.endAngle, 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "7482962148e8d758338d8a28f589f317e1e42ba4" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 17 | base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 18 | - platform: android 19 | create_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 20 | base_revision: 7482962148e8d758338d8a28f589f317e1e42ba4 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/src/widget_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:vector_math/vector_math_64.dart' as vector; 3 | 4 | /// Helper class to determine the size and position of a widget 5 | class WidgetParams { 6 | WidgetParams({ 7 | required this.xPosition, 8 | required this.yPosition, 9 | required this.rect, 10 | }); 11 | 12 | WidgetParams.fromContext(BuildContext? context) { 13 | // Get the widget RenderObject 14 | final object = context?.findRenderObject(); 15 | // Get the dimensions and position of the widget 16 | final translation = 17 | object?.getTransformTo(null).getTranslation() ?? vector.Vector3.zero(); 18 | final size = object?.semanticBounds.size ?? Size.zero; 19 | 20 | xPosition = translation.x; 21 | yPosition = translation.y; 22 | rect = Rect.fromLTWH(translation.x, translation.y, size.width, size.height); 23 | } 24 | 25 | late double xPosition; 26 | late double yPosition; 27 | late Rect rect; 28 | 29 | @override 30 | String toString() { 31 | return 'X,Y,rect: $xPosition,$yPosition $rect'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "star_menu", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "star_menu (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | }, 18 | { 19 | "name": "star_menu (release mode)", 20 | "request": "launch", 21 | "type": "dart", 22 | "flutterMode": "release" 23 | }, 24 | { 25 | "name": "main2", 26 | "request": "launch", 27 | "type": "dart", 28 | "cwd": "example", 29 | "args": ["-t", "lib/main2.dart"], 30 | "flutterMode": "debug", 31 | "program": "lib/main2.dart" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Marco Bavagnoli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/src/params/boundary_background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// boundary background parameters 4 | @immutable 5 | class BoundaryBackground { 6 | BoundaryBackground({ 7 | this.color = Colors.white, 8 | this.padding = const EdgeInsets.all(8), 9 | Decoration? decoration, 10 | this.blurSigmaX, 11 | this.blurSigmaY, 12 | }) : decoration = decoration ?? 13 | BoxDecoration( 14 | borderRadius: BorderRadius.circular(8), 15 | color: color, 16 | ); 17 | 18 | /// color of the boundary background 19 | final Color color; 20 | 21 | /// padding 22 | final EdgeInsets padding; 23 | 24 | /// background Container widget decoration 25 | final Decoration? decoration; 26 | 27 | /// background blur sigmaX value 28 | final double? blurSigmaX; 29 | 30 | /// background blur sigmaY value 31 | final double? blurSigmaY; 32 | 33 | BoundaryBackground copyWith({ 34 | Color? color, 35 | EdgeInsets? padding, 36 | Decoration? decoration, 37 | }) { 38 | return BoundaryBackground( 39 | color: color ?? this.color, 40 | padding: padding ?? this.padding, 41 | decoration: decoration ?? this.decoration, 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /star_menu.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /lib/src/params/background_params.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// class to define background 4 | @immutable 5 | class BackgroundParams { 6 | const BackgroundParams({ 7 | this.animatedBlur = false, 8 | this.sigmaX = 0.0, 9 | this.sigmaY = 0.0, 10 | this.animatedBackgroundColor = false, 11 | this.backgroundColor = Colors.transparent, 12 | }); 13 | 14 | /// Animate background blur from 0.0 to sigma if true 15 | final bool animatedBlur; 16 | 17 | /// Horizontal blur 18 | final double sigmaX; 19 | 20 | /// Vertical blur 21 | final double sigmaY; 22 | 23 | /// Animate [backgroundColor] from transparent if true 24 | final bool animatedBackgroundColor; 25 | 26 | /// Background color 27 | final Color backgroundColor; 28 | 29 | BackgroundParams copyWith({ 30 | bool? animatedBlur, 31 | double? sigmaX, 32 | double? sigmaY, 33 | bool? animatedBackgroundColor, 34 | Color? backgroundColor, 35 | }) { 36 | return BackgroundParams( 37 | animatedBlur: animatedBlur ?? this.animatedBlur, 38 | sigmaX: sigmaX ?? this.sigmaX, 39 | sigmaY: sigmaY ?? this.sigmaY, 40 | animatedBackgroundColor: 41 | animatedBackgroundColor ?? this.animatedBackgroundColor, 42 | backgroundColor: backgroundColor ?? this.backgroundColor, 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/dinamyc_star_menu.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:star_menu/src/star_menu.dart'; 4 | 5 | // Creates an overlay to display the StarMenu and open it 6 | class StarMenuOverlay { 7 | static StarMenu? _sm; 8 | static OverlayState? _overlayState; 9 | static OverlayEntry? _overlayEntry; 10 | 11 | // Build the StarMenu on an overlay 12 | static void displayStarMenu(BuildContext context, StarMenu starMenu) { 13 | _sm = starMenu; 14 | // Retrieve the parent Overlay 15 | _overlayState = Overlay.of(context); 16 | 17 | // Generate the Stack containing all StarItems that will 18 | // be displayed onto the Overlay 19 | _overlayEntry = OverlayEntry( 20 | builder: (BuildContext context) { 21 | return Stack( 22 | children: [ 23 | starMenu, 24 | ], 25 | ); 26 | }, 27 | ); 28 | 29 | // Add it to the Overlay 30 | if (_overlayEntry != null) { 31 | _overlayState!.insert(_overlayEntry!); 32 | } 33 | } 34 | 35 | static void dispose() { 36 | _overlayEntry?.remove(); 37 | _overlayEntry = null; 38 | _sm = null; 39 | } 40 | 41 | static bool isMounted(State state) { 42 | // Is it correct to use the hashCode?? 43 | return _overlayEntry != null && state.widget.hashCode == _sm.hashCode; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | star_menu_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | WORK/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Flutter.podspec 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/ephemeral 65 | **/ios/Flutter/app.flx 66 | **/ios/Flutter/app.zip 67 | **/ios/Flutter/flutter_assets/ 68 | **/ios/Flutter/flutter_export_environment.sh 69 | **/ios/ServiceDefinitions.json 70 | **/ios/Runner/GeneratedPluginRegistrant.* 71 | 72 | # Exceptions to above rules. 73 | !**/ios/**/default.mode1v3 74 | !**/ios/**/default.mode2v3 75 | !**/ios/**/default.pbxuser 76 | !**/ios/**/default.perspectivev3 77 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace "com.example.example" 27 | compileSdk flutter.compileSdkVersion 28 | ndkVersion flutter.ndkVersion 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.example.example" 38 | // You can update the following values to match your application needs. 39 | // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. 40 | minSdkVersion flutter.minSdkVersion 41 | targetSdkVersion flutter.targetSdkVersion 42 | versionCode flutterVersionCode.toInteger() 43 | versionName flutterVersionName 44 | } 45 | 46 | buildTypes { 47 | release { 48 | // TODO: Add your own signing config for the release build. 49 | // Signing with the debug keys for now, so `flutter run --release` works. 50 | signingConfig signingConfigs.debug 51 | } 52 | } 53 | } 54 | 55 | flutter { 56 | source '../..' 57 | } 58 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 14 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | 32 | 33 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | 11 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 12 | # which isn't available in 3.10. 13 | function(list_prepend LIST_NAME PREFIX) 14 | set(NEW_LIST "") 15 | foreach(element ${${LIST_NAME}}) 16 | list(APPEND NEW_LIST "${PREFIX}${element}") 17 | endforeach(element) 18 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 19 | endfunction() 20 | 21 | # === Flutter Library === 22 | # System-level dependencies. 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 25 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 26 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 27 | 28 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 29 | 30 | # Published to parent scope for install step. 31 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 32 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 33 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 34 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 35 | 36 | list(APPEND FLUTTER_LIBRARY_HEADERS 37 | "fl_basic_message_channel.h" 38 | "fl_binary_codec.h" 39 | "fl_binary_messenger.h" 40 | "fl_dart_project.h" 41 | "fl_engine.h" 42 | "fl_json_message_codec.h" 43 | "fl_json_method_codec.h" 44 | "fl_message_codec.h" 45 | "fl_method_call.h" 46 | "fl_method_channel.h" 47 | "fl_method_codec.h" 48 | "fl_method_response.h" 49 | "fl_plugin_registrar.h" 50 | "fl_plugin_registry.h" 51 | "fl_standard_message_codec.h" 52 | "fl_standard_method_codec.h" 53 | "fl_string_codec.h" 54 | "fl_value.h" 55 | "fl_view.h" 56 | "flutter_linux.h" 57 | ) 58 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 59 | add_library(flutter INTERFACE) 60 | target_include_directories(flutter INTERFACE 61 | "${EPHEMERAL_DIR}" 62 | ) 63 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 64 | target_link_libraries(flutter INTERFACE 65 | PkgConfig::GTK 66 | PkgConfig::GLIB 67 | PkgConfig::GIO 68 | ) 69 | add_dependencies(flutter flutter_assemble) 70 | 71 | # === Flutter tool backend === 72 | # _phony_ is a non-existent file to force this command to run every time, 73 | # since currently there's no way to get a full input/output list from the 74 | # flutter tool. 75 | add_custom_command( 76 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 77 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 78 | COMMAND ${CMAKE_COMMAND} -E env 79 | ${FLUTTER_TOOL_ENVIRONMENT} 80 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 81 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 82 | VERBATIM 83 | ) 84 | add_custom_target(flutter_assemble DEPENDS 85 | "${FLUTTER_LIBRARY}" 86 | ${FLUTTER_LIBRARY_HEADERS} 87 | ) 88 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ##### [4.0.1] - 25 Apr 2024 2 | * fix overlay was not rooted, ie when a shell route is displayed the menu coordinates wasn't correct 3 | 4 | ##### [4.0.0] - 1 Mar 2024 5 | * breaking change: removed unused `context` parameter from `StarMenuParameters.arc` factory 6 | 7 | ##### [3.1.9] - 1 Mar 2024 8 | * fixed a bug when dragging outside the menu items 9 | * code optimized and finally linted 10 | * updated v3 for the upcoming v4 11 | 12 | ##### [3.1.8] - 24 Feb 2024 13 | * fixed a bug when dragging outside the menu items 14 | * code optimized and finally linted 15 | 16 | ##### [3.1.6] - 7 Feb 2024 17 | * Breaking change bug fix: StarMenuParameters.dropdown factory has an unwanted shift on the X axis 18 | 19 | ##### [3.1.5] - 20 Feb 2023 20 | * fixed doc image links 21 | 22 | ##### [3.1.4] - 20 Feb 2023 23 | * added blur parameters to the [BoundaryBackground] thanks to Hyungil Kang 24 | 25 | ##### [3.1.3] - 6 Feb 2023 26 | * fixed sigmaX and sigmaY for the blurred background 27 | 28 | ##### [3.1.2] - 23 Dec 2022 29 | * breaking: due to the [lazyItems] added to the [addStarMenu] extension, all the parameters to that mixin are now optional ex: 30 | ``` 31 | .addStarMenu( 32 | items: upperMenuItems, 33 | ... 34 | ``` 35 | 36 | ##### [3.1.1] - 12 Dec 2022 37 | * added [lazyItems] and [onStateChanged] parameters to [addStarMenu] extension 38 | 39 | ##### [3.1.0+1] - 26 Oct 2022 40 | * it's now possible to open a menu programmatically with [StarMenuController]. 41 | * it's now possible to open a menu programmatically by passing [parentContext] to [StarMenu]. 42 | * added [useTouchAsCenter] to [StarMenuParameters] to use the touch position as the menu center. 43 | 44 | ##### [3.0.0+2] - 23 Sep 2022 45 | * added a new main.dart example 46 | * added `onHoverScale` in `StarMenuParameters` to scale items when mouse hover (desktop only) 47 | * added `BoundaryBackground` to set a background behind all the menu items 48 | * the opening animation now starts from the first menu item 49 | * added `dropdown`, `arc` and `panel` menu presets 50 | * breaking change: [StarMenuParameters.onItemTapped] moved into [StarMenu] widget 51 | 52 | ##### [2.2.0] - 23 Jul 2022 53 | * added [useLongpress] and [longPressDuration] to open the menu with a long press 54 | 55 | ##### [2.1.3] - 13 Mar 2022 56 | * code formatted 57 | 58 | ##### [2.1.2] - 12 Mar 2022 59 | * fixed wrong menu position when using RTL 60 | 61 | ##### [2.1.1] - 10 Nov 2021 62 | * added `onStateChanged` callback which triggers `closed`, `closing`, `opening`, `open` states 63 | 64 | ##### [2.1.0] - 29 Oct 2021 65 | * added a movement threshold for touches: 66 | if a movement of more the 10 px occurs after touching the 67 | widget, it will not open 68 | * bug fix when changing device rotation 69 | * added `lazyItems` property which builds menu items at runtime 70 | 71 | ##### [2.0.1] - 22 Aug 2021 72 | * support for hot reload 73 | 74 | ##### [2.0.0+3] - 10 Aug 2021 75 | * removed dart:io dependency for web compatibility 76 | * bug fix in web version when animating the blur 77 | 78 | ##### [2.0.0+2] - 10 Aug 2021 79 | * added some documentation 80 | 81 | ##### [2.0.0+1] - 10 Aug 2021 82 | * breaking change: code rewritten to remove the 'keys boilerplate' (see the doc) and performances issue 83 | 84 | ##### [1.0.4] - 12 Jun 2019 85 | * blurring background while opening 86 | 87 | ##### [1.0.2] - 31 Mar 2019 88 | * fixed some naming conventions and formats for pub 89 | 90 | 91 | ##### [1.0.0] - 31 Mar 2019 92 | * initial release. -------------------------------------------------------------------------------- /lib/src/star_item.dart: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019-2021, Marco Bavagnoli 3 | All rights reserved. 4 | */ 5 | import 'dart:ui'; 6 | 7 | import 'package:flutter/material.dart'; 8 | 9 | import 'package:star_menu/src/center_widget.dart'; 10 | 11 | class StarItem extends StatelessWidget { 12 | const StarItem({ 13 | required Key key, 14 | required this.totItems, 15 | required this.index, 16 | required this.itemMatrix, 17 | required this.onItemTapped, 18 | required this.child, 19 | this.animValue = 0.0, 20 | this.center = Offset.zero, 21 | this.shift = Offset.zero, 22 | this.rotateRAD = 0.0, 23 | this.scale = 1.0, 24 | this.onHoverScale = 1.0, 25 | }) : assert(totItems > 0, '[totItems] must be > 0'), 26 | assert( 27 | index >= 0 && index < totItems, 28 | '0<[index]<[totItems] not in range ', 29 | ), 30 | super(key: key); 31 | 32 | final double animValue; 33 | final int totItems; 34 | final int index; 35 | final Offset center; 36 | final Offset shift; 37 | final Matrix4 itemMatrix; 38 | final double rotateRAD; 39 | final double scale; 40 | final double onHoverScale; 41 | final void Function(int index) onItemTapped; 42 | final Widget child; 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | // stretch item animation: the last one starts when animValue reach c 47 | // item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 48 | // |------|------|------|------|------|------|------|------|------| 49 | // 0.0 0.3 1.0 50 | // ie: item3 starts when animValue reach 0.3. 51 | // So for item3, lerp animValue to be 0.0 when it is 0.3 52 | final step = (1.0 / totItems) * index; 53 | final stepDelta = 1.0 / (1 - step); 54 | final a = (animValue - step < 0.0 ? 0.0 : animValue - step) * stepDelta; 55 | 56 | final onHover = ValueNotifier(false); 57 | 58 | // lerp from parentBounds position to items end position 59 | final mat = Matrix4.identity() 60 | ..translate( 61 | lerpDouble(center.dx, shift.dx, a) ?? 0, 62 | lerpDouble(center.dy, shift.dy, a) ?? 0, 63 | ); 64 | if (rotateRAD > 0) mat.setRotationZ((1.0 - a) * rotateRAD); 65 | // if (scale < 1) 66 | // mat.scale(lerpDouble(scale, 1.0, a)); 67 | final newScale = lerpDouble(scale, 1.0, a)!; 68 | 69 | return Transform( 70 | // key: itemKeys.elementAt(index), 71 | transform: mat, 72 | child: CenteredWidget( 73 | child: Opacity( 74 | opacity: a, 75 | child: Listener( 76 | behavior: HitTestBehavior.deferToChild, 77 | onPointerUp: (_) => onItemTapped(index), 78 | child: MouseRegion( 79 | onEnter: (event) => onHover.value = true, 80 | onExit: (event) => onHover.value = false, 81 | child: ValueListenableBuilder( 82 | valueListenable: onHover, 83 | builder: (_, isHover, __) { 84 | return AnimatedScale( 85 | scale: a < 1.0 86 | ? newScale 87 | : (isHover ? newScale * onHoverScale : newScale), 88 | duration: const Duration(milliseconds: 200), 89 | child: child, 90 | ); 91 | }, 92 | ), 93 | ), 94 | ), 95 | ), 96 | ), 97 | ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | star_menu_example 27 | 28 | 29 | 30 | 33 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /example/linux/my_application.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | #include 4 | #ifdef GDK_WINDOWING_X11 5 | #include 6 | #endif 7 | 8 | #include "flutter/generated_plugin_registrant.h" 9 | 10 | struct _MyApplication { 11 | GtkApplication parent_instance; 12 | char** dart_entrypoint_arguments; 13 | }; 14 | 15 | G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) 16 | 17 | // Implements GApplication::activate. 18 | static void my_application_activate(GApplication* application) { 19 | MyApplication* self = MY_APPLICATION(application); 20 | GtkWindow* window = 21 | GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); 22 | 23 | // Use a header bar when running in GNOME as this is the common style used 24 | // by applications and is the setup most users will be using (e.g. Ubuntu 25 | // desktop). 26 | // If running on X and not using GNOME then just use a traditional title bar 27 | // in case the window manager does more exotic layout, e.g. tiling. 28 | // If running on Wayland assume the header bar will work (may need changing 29 | // if future cases occur). 30 | gboolean use_header_bar = TRUE; 31 | #ifdef GDK_WINDOWING_X11 32 | GdkScreen *screen = gtk_window_get_screen(window); 33 | if (GDK_IS_X11_SCREEN(screen)) { 34 | const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); 35 | if (g_strcmp0(wm_name, "GNOME Shell") != 0) { 36 | use_header_bar = FALSE; 37 | } 38 | } 39 | #endif 40 | if (use_header_bar) { 41 | GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); 42 | gtk_widget_show(GTK_WIDGET(header_bar)); 43 | gtk_header_bar_set_title(header_bar, "star_menu_example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } 47 | else { 48 | gtk_window_set_title(window, "star_menu_example"); 49 | } 50 | 51 | gtk_window_set_default_size(window, 650, 950); 52 | gtk_widget_show(GTK_WIDGET(window)); 53 | 54 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 55 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 56 | 57 | FlView* view = fl_view_new(project); 58 | gtk_widget_show(GTK_WIDGET(view)); 59 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 60 | 61 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 62 | 63 | gtk_widget_grab_focus(GTK_WIDGET(view)); 64 | } 65 | 66 | // Implements GApplication::local_command_line. 67 | static gboolean my_application_local_command_line(GApplication* application, gchar ***arguments, int *exit_status) { 68 | MyApplication* self = MY_APPLICATION(application); 69 | // Strip out the first argument as it is the binary name. 70 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 71 | 72 | g_autoptr(GError) error = nullptr; 73 | if (!g_application_register(application, nullptr, &error)) { 74 | g_warning("Failed to register: %s", error->message); 75 | *exit_status = 1; 76 | return TRUE; 77 | } 78 | 79 | g_application_activate(application); 80 | *exit_status = 0; 81 | 82 | return TRUE; 83 | } 84 | 85 | // Implements GObject::dispose. 86 | static void my_application_dispose(GObject *object) { 87 | MyApplication* self = MY_APPLICATION(object); 88 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 89 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 90 | } 91 | 92 | static void my_application_class_init(MyApplicationClass* klass) { 93 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 94 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 95 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 96 | } 97 | 98 | static void my_application_init(MyApplication* self) {} 99 | 100 | MyApplication* my_application_new() { 101 | return MY_APPLICATION(g_object_new(my_application_get_type(), 102 | "application-id", APPLICATION_ID, 103 | "flags", G_APPLICATION_NON_UNIQUE, 104 | nullptr)); 105 | } 106 | -------------------------------------------------------------------------------- /example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(runner LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "star_menu_example") 5 | set(APPLICATION_ID "com.bavagnoli.star_menu_example") 6 | 7 | cmake_policy(SET CMP0063 NEW) 8 | 9 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 10 | 11 | # Root filesystem for cross-building. 12 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 13 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 14 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 18 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 19 | endif() 20 | 21 | # Configure build options. 22 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 23 | set(CMAKE_BUILD_TYPE "Debug" CACHE 24 | STRING "Flutter build mode" FORCE) 25 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 26 | "Debug" "Profile" "Release") 27 | endif() 28 | 29 | # Compilation settings that should be applied to most targets. 30 | function(APPLY_STANDARD_SETTINGS TARGET) 31 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 32 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 33 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 34 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 35 | endfunction() 36 | 37 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 38 | 39 | # Flutter library and tool build rules. 40 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 41 | 42 | # System-level dependencies. 43 | find_package(PkgConfig REQUIRED) 44 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 45 | 46 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 47 | 48 | # Application build 49 | add_executable(${BINARY_NAME} 50 | "main.cc" 51 | "my_application.cc" 52 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 53 | ) 54 | apply_standard_settings(${BINARY_NAME}) 55 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 56 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 57 | add_dependencies(${BINARY_NAME} flutter_assemble) 58 | # Only the install-generated bundle's copy of the executable will launch 59 | # correctly, since the resources must in the right relative locations. To avoid 60 | # people trying to run the unbundled copy, put it in a subdirectory instead of 61 | # the default top-level location. 62 | set_target_properties(${BINARY_NAME} 63 | PROPERTIES 64 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 65 | ) 66 | 67 | # Generated plugin build rules, which manage building the plugins and adding 68 | # them to the application. 69 | include(flutter/generated_plugins.cmake) 70 | 71 | 72 | # === Installation === 73 | # By default, "installing" just makes a relocatable bundle in the build 74 | # directory. 75 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 76 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 77 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 78 | endif() 79 | 80 | # Start with a clean build bundle directory every time. 81 | install(CODE " 82 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 83 | " COMPONENT Runtime) 84 | 85 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 86 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 87 | 88 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 89 | COMPONENT Runtime) 90 | 91 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 92 | COMPONENT Runtime) 93 | 94 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 95 | COMPONENT Runtime) 96 | 97 | if(PLUGIN_BUNDLED_LIBRARIES) 98 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 99 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 100 | COMPONENT Runtime) 101 | endif() 102 | 103 | # Fully re-copy the assets directory on each build to avoid having stale files 104 | # from a previous install. 105 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 106 | install(CODE " 107 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 108 | " COMPONENT Runtime) 109 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 110 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 111 | 112 | # Install the AOT library on non-Debug builds only. 113 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 114 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 115 | COMPONENT Runtime) 116 | endif() 117 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.1" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.18.0" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.1" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_test: 58 | dependency: "direct dev" 59 | description: flutter 60 | source: sdk 61 | version: "0.0.0" 62 | leak_tracker: 63 | dependency: transitive 64 | description: 65 | name: leak_tracker 66 | sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" 67 | url: "https://pub.dev" 68 | source: hosted 69 | version: "10.0.0" 70 | leak_tracker_flutter_testing: 71 | dependency: transitive 72 | description: 73 | name: leak_tracker_flutter_testing 74 | sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "2.0.1" 78 | leak_tracker_testing: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker_testing 82 | sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "2.0.1" 86 | matcher: 87 | dependency: transitive 88 | description: 89 | name: matcher 90 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "0.12.16+1" 94 | material_color_utilities: 95 | dependency: transitive 96 | description: 97 | name: material_color_utilities 98 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "0.8.0" 102 | meta: 103 | dependency: transitive 104 | description: 105 | name: meta 106 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "1.11.0" 110 | path: 111 | dependency: transitive 112 | description: 113 | name: path 114 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "1.9.0" 118 | sky_engine: 119 | dependency: transitive 120 | description: flutter 121 | source: sdk 122 | version: "0.0.99" 123 | source_span: 124 | dependency: transitive 125 | description: 126 | name: source_span 127 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 128 | url: "https://pub.dev" 129 | source: hosted 130 | version: "1.10.0" 131 | stack_trace: 132 | dependency: transitive 133 | description: 134 | name: stack_trace 135 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "1.11.1" 139 | stream_channel: 140 | dependency: transitive 141 | description: 142 | name: stream_channel 143 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "2.1.2" 147 | string_scanner: 148 | dependency: transitive 149 | description: 150 | name: string_scanner 151 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.2.0" 155 | term_glyph: 156 | dependency: transitive 157 | description: 158 | name: term_glyph 159 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "1.2.1" 163 | test_api: 164 | dependency: transitive 165 | description: 166 | name: test_api 167 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "0.6.1" 171 | vector_math: 172 | dependency: "direct main" 173 | description: 174 | name: vector_math 175 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "2.1.4" 179 | very_good_analysis: 180 | dependency: "direct dev" 181 | description: 182 | name: very_good_analysis 183 | sha256: "9ae7f3a3bd5764fb021b335ca28a34f040cd0ab6eec00a1b213b445dae58a4b8" 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "5.1.0" 187 | vm_service: 188 | dependency: transitive 189 | description: 190 | name: vm_service 191 | sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "13.0.0" 195 | sdks: 196 | dart: ">=3.2.0 <4.0.0" 197 | flutter: ">=1.17.0" 198 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.1" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.3.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.1" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.18.0" 44 | cupertino_icons: 45 | dependency: "direct main" 46 | description: 47 | name: cupertino_icons 48 | sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.6" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.1" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | leak_tracker: 71 | dependency: transitive 72 | description: 73 | name: leak_tracker 74 | sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "10.0.0" 78 | leak_tracker_flutter_testing: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker_flutter_testing 82 | sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "2.0.1" 86 | leak_tracker_testing: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker_testing 90 | sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "2.0.1" 94 | matcher: 95 | dependency: transitive 96 | description: 97 | name: matcher 98 | sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "0.12.16+1" 102 | material_color_utilities: 103 | dependency: transitive 104 | description: 105 | name: material_color_utilities 106 | sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "0.8.0" 110 | meta: 111 | dependency: transitive 112 | description: 113 | name: meta 114 | sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "1.11.0" 118 | path: 119 | dependency: transitive 120 | description: 121 | name: path 122 | sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "1.9.0" 126 | sky_engine: 127 | dependency: transitive 128 | description: flutter 129 | source: sdk 130 | version: "0.0.99" 131 | source_span: 132 | dependency: transitive 133 | description: 134 | name: source_span 135 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 136 | url: "https://pub.dev" 137 | source: hosted 138 | version: "1.10.0" 139 | stack_trace: 140 | dependency: transitive 141 | description: 142 | name: stack_trace 143 | sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "1.11.1" 147 | star_menu: 148 | dependency: "direct main" 149 | description: 150 | path: ".." 151 | relative: true 152 | source: path 153 | version: "4.0.0" 154 | stream_channel: 155 | dependency: transitive 156 | description: 157 | name: stream_channel 158 | sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 159 | url: "https://pub.dev" 160 | source: hosted 161 | version: "2.1.2" 162 | string_scanner: 163 | dependency: transitive 164 | description: 165 | name: string_scanner 166 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 167 | url: "https://pub.dev" 168 | source: hosted 169 | version: "1.2.0" 170 | term_glyph: 171 | dependency: transitive 172 | description: 173 | name: term_glyph 174 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 175 | url: "https://pub.dev" 176 | source: hosted 177 | version: "1.2.1" 178 | test_api: 179 | dependency: transitive 180 | description: 181 | name: test_api 182 | sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" 183 | url: "https://pub.dev" 184 | source: hosted 185 | version: "0.6.1" 186 | vector_math: 187 | dependency: transitive 188 | description: 189 | name: vector_math 190 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 191 | url: "https://pub.dev" 192 | source: hosted 193 | version: "2.1.4" 194 | very_good_analysis: 195 | dependency: "direct dev" 196 | description: 197 | name: very_good_analysis 198 | sha256: "9ae7f3a3bd5764fb021b335ca28a34f040cd0ab6eec00a1b213b445dae58a4b8" 199 | url: "https://pub.dev" 200 | source: hosted 201 | version: "5.1.0" 202 | vm_service: 203 | dependency: transitive 204 | description: 205 | name: vm_service 206 | sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "13.0.0" 210 | sdks: 211 | dart: ">=3.2.0 <4.0.0" 212 | flutter: ">=1.17.0" 213 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /lib/src/params/star_menu_params.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_redundant_argument_values 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:star_menu/src/params/background_params.dart'; 5 | import 'package:star_menu/src/params/boundary_background.dart'; 6 | import 'package:star_menu/src/params/circle_shape_params.dart'; 7 | import 'package:star_menu/src/params/grid_shape_params.dart'; 8 | import 'package:star_menu/src/params/linear_shape_params.dart'; 9 | import 'package:star_menu/src/star_menu.dart'; 10 | 11 | /// class which is used to feed [StarMenu.params] 12 | @immutable 13 | class StarMenuParameters { 14 | const StarMenuParameters({ 15 | this.linearShapeParams = const LinearShapeParams(), 16 | this.circleShapeParams = const CircleShapeParams(), 17 | this.gridShapeParams = const GridShapeParams(), 18 | this.backgroundParams = const BackgroundParams(), 19 | this.shape = MenuShape.circle, 20 | this.boundaryBackground, 21 | this.useLongPress = false, 22 | this.longPressDuration = const Duration(milliseconds: 500), 23 | this.onHoverScale = 1.0, 24 | this.openDurationMs = 400, 25 | this.closeDurationMs = 150, 26 | this.rotateItemsAnimationAngle = 0.0, 27 | this.startItemScaleAnimation = 1.0, 28 | this.centerOffset = Offset.zero, 29 | this.useScreenCenter = false, 30 | this.useTouchAsCenter = false, 31 | this.checkItemsScreenBoundaries = false, 32 | this.checkMenuScreenBoundaries = true, 33 | this.animationCurve = Curves.fastOutSlowIn, 34 | }); 35 | 36 | /// preset to display items in an arc shape 37 | factory StarMenuParameters.arc( 38 | ArcType type, { 39 | double radiusX = 130, 40 | double radiusY = 130, 41 | }) { 42 | var start = 0.0; 43 | var end = 0.0; 44 | switch (type) { 45 | case ArcType.semiUp: 46 | start = 0.0; 47 | end = 180.0; 48 | case ArcType.semiDown: 49 | start = 180.0; 50 | end = 360.0; 51 | case ArcType.semiLeft: 52 | start = 90.0; 53 | end = 270.0; 54 | case ArcType.semiRight: 55 | start = -90.0; 56 | end = 90.0; 57 | case ArcType.quarterTopRight: 58 | start = 0.0; 59 | end = 90.0; 60 | case ArcType.quarterTopLeft: 61 | start = 90.0; 62 | end = 180.0; 63 | case ArcType.quarterBottomRight: 64 | start = 270.0; 65 | end = 360.0; 66 | case ArcType.quarterBottomLeft: 67 | start = 180.0; 68 | end = 270.0; 69 | } 70 | return StarMenuParameters( 71 | shape: MenuShape.circle, 72 | circleShapeParams: CircleShapeParams( 73 | startAngle: start, 74 | endAngle: end, 75 | radiusX: radiusX, 76 | radiusY: radiusY, 77 | ), 78 | backgroundParams: const BackgroundParams( 79 | backgroundColor: Colors.transparent, 80 | ), 81 | onHoverScale: 1.5, 82 | ); 83 | } 84 | 85 | /// preset to display a grid menu inscribed into a card 86 | factory StarMenuParameters.panel(BuildContext context, {int columns = 3}) { 87 | return StarMenuParameters( 88 | shape: MenuShape.grid, 89 | onHoverScale: 1.3, 90 | gridShapeParams: GridShapeParams( 91 | columns: columns, 92 | columnsSpaceV: 20, 93 | columnsSpaceH: 40, 94 | ), 95 | backgroundParams: const BackgroundParams( 96 | backgroundColor: Colors.transparent, 97 | ), 98 | boundaryBackground: BoundaryBackground( 99 | padding: const EdgeInsets.all(16), 100 | decoration: BoxDecoration( 101 | borderRadius: BorderRadius.circular(8), 102 | color: Theme.of(context).cardColor, 103 | boxShadow: kElevationToShadow[6], 104 | ), 105 | ), 106 | ); 107 | } 108 | 109 | /// preset to display a dropdown menu like 110 | factory StarMenuParameters.dropdown(BuildContext context) { 111 | return StarMenuParameters( 112 | shape: MenuShape.linear, 113 | centerOffset: const Offset(0, 40), 114 | openDurationMs: 200, 115 | closeDurationMs: 60, 116 | startItemScaleAnimation: 1, 117 | linearShapeParams: const LinearShapeParams( 118 | space: 16, 119 | angle: 270, 120 | ), 121 | backgroundParams: const BackgroundParams( 122 | backgroundColor: Colors.transparent, 123 | ), 124 | boundaryBackground: BoundaryBackground( 125 | padding: const EdgeInsets.all(12), 126 | decoration: BoxDecoration( 127 | borderRadius: BorderRadius.circular(4), 128 | color: Theme.of(context).popupMenuTheme.color ?? 129 | Theme.of(context).cardColor, 130 | boxShadow: kElevationToShadow[6], 131 | ), 132 | ), 133 | ); 134 | } 135 | 136 | /// Menu shape kind: [MenuShape.circle], [MenuShape.linear], [MenuShape.grid] 137 | final MenuShape shape; 138 | 139 | /// put a background behind all the items boundary 140 | final BoundaryBackground? boundaryBackground; 141 | 142 | /// parameters for the linear shape 143 | final LinearShapeParams linearShapeParams; 144 | 145 | /// parameters for the circle shape 146 | final CircleShapeParams circleShapeParams; 147 | 148 | /// parameters for the grid shape 149 | final GridShapeParams gridShapeParams; 150 | 151 | /// parameters for the background 152 | final BackgroundParams backgroundParams; 153 | 154 | /// Use long press behavior instead of a tap to open the menu 155 | final bool useLongPress; 156 | 157 | /// scale item when mouse is hover (desktop only) 158 | final double onHoverScale; 159 | 160 | /// long press duration 161 | final Duration longPressDuration; 162 | 163 | /// Open animation duration 164 | final int openDurationMs; 165 | 166 | /// Close animation duration 167 | final int closeDurationMs; 168 | 169 | /// Starting rotation angle of the items that will 170 | /// reach 0 DEG when animation ends 171 | final double rotateItemsAnimationAngle; 172 | 173 | /// Starting scale of the items that will reach 1 when animation ends 174 | final double startItemScaleAnimation; 175 | 176 | /// Shift offset of menu center from the center of parent widget 177 | final Offset centerOffset; 178 | 179 | /// Use the screen center instead of parent widget center 180 | final bool useScreenCenter; 181 | 182 | /// Use the touch coordinate as the menu center 183 | final bool useTouchAsCenter; 184 | 185 | /// Checks if the whole menu boundaries exceed screen edges, 186 | /// if so set it in place to be all visible 187 | final bool checkItemsScreenBoundaries; 188 | 189 | /// Checks if items exceed screen edges, if so set them in place to be visible 190 | final bool checkMenuScreenBoundaries; 191 | 192 | /// Animation curve kind to use 193 | final Curve animationCurve; 194 | 195 | StarMenuParameters copyWith({ 196 | MenuShape? shape, 197 | BoundaryBackground? boundaryBackground, 198 | LinearShapeParams? linearShapeParams, 199 | CircleShapeParams? circleShapeParams, 200 | GridShapeParams? gridShapeParams, 201 | BackgroundParams? backgroundParams, 202 | bool? useLongPress, 203 | double? onHoverScale, 204 | Duration? longPressDuration, 205 | int? openDurationMs, 206 | int? closeDurationMs, 207 | double? rotateItemsAnimationAngle, 208 | double? startItemScaleAnimation, 209 | Offset? centerOffset, 210 | bool? useScreenCenter, 211 | bool? useTouchAsCenter, 212 | bool? checkItemsScreenBoundaries, 213 | bool? checkMenuScreenBoundaries, 214 | Curve? animationCurve, 215 | }) { 216 | return StarMenuParameters( 217 | shape: shape ?? this.shape, 218 | boundaryBackground: boundaryBackground ?? this.boundaryBackground, 219 | linearShapeParams: linearShapeParams ?? this.linearShapeParams, 220 | circleShapeParams: circleShapeParams ?? this.circleShapeParams, 221 | gridShapeParams: gridShapeParams ?? this.gridShapeParams, 222 | backgroundParams: backgroundParams ?? this.backgroundParams, 223 | useLongPress: useLongPress ?? this.useLongPress, 224 | onHoverScale: onHoverScale ?? this.onHoverScale, 225 | longPressDuration: longPressDuration ?? this.longPressDuration, 226 | openDurationMs: openDurationMs ?? this.openDurationMs, 227 | closeDurationMs: closeDurationMs ?? this.closeDurationMs, 228 | rotateItemsAnimationAngle: 229 | rotateItemsAnimationAngle ?? this.rotateItemsAnimationAngle, 230 | startItemScaleAnimation: 231 | startItemScaleAnimation ?? this.startItemScaleAnimation, 232 | centerOffset: centerOffset ?? this.centerOffset, 233 | useScreenCenter: useScreenCenter ?? this.useScreenCenter, 234 | useTouchAsCenter: useTouchAsCenter ?? this.useTouchAsCenter, 235 | checkItemsScreenBoundaries: 236 | checkItemsScreenBoundaries ?? this.checkItemsScreenBoundaries, 237 | checkMenuScreenBoundaries: 238 | checkMenuScreenBoundaries ?? this.checkMenuScreenBoundaries, 239 | animationCurve: animationCurve ?? this.animationCurve, 240 | ); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | StarMenu
3 | Easy and Fast Way to build Context Menus 4 |

5 | 6 | 7 | [![Pub Version](https://img.shields.io/pub/v/star_menu?style=flat-square&logo=dart)](https://pub.dev/packages/star_menu) 8 | ![Pub Likes](https://img.shields.io/pub/likes/star_menu) 9 | ![Pub Likes](https://img.shields.io/pub/points/star_menu) 10 | ![Pub Likes](https://img.shields.io/pub/popularity/star_menu) 11 | ![GitHub repo size](https://img.shields.io/github/repo-size/alnitak/flutter_star_menu?style=flat-square) 12 | ![GitHub forks](https://img.shields.io/github/forks/alnitak/flutter_star_menu?style=flat-square) 13 | ![GitHub stars](https://img.shields.io/github/stars/alnitak/flutter_star_menu?style=flat-square) 14 | ![GitHub license](https://img.shields.io/github/license/alnitak/flutter_star_menu?style=flat-square) 15 | 16 | [pub.dev link](https://pub.dev/packages/star_menu) 17 | 18 | ![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/dont_buy_me_coffe.png/) 19 | 20 | *Instead, a star would be wonderful! ;)* 21 | 22 | 23 | A simple way to attach a popup menu to any widget with any widget as menu entries. 24 | Menu entry widgets can bind a sub-menu with different shapes. 25 | Multiple ways to fine-tune animation and position. 26 | 27 | ![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/StarMenuDemo2.gif) 28 | ![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/StarMenuDemo.gif) 29 | 30 | Every widgets can be tapped to display a popup menu! 31 | There are currently 3 shapes to choose: 32 | 33 | - `linear`: items are lined by a given angle with a given space between them and with a 3-way alignment. 34 | - `circle`: items are lined up in a circle shape with a given radius and a star-end angle. 35 | - `grid`: items are aligned in a grid shape with N columns and a given horizontal and vertical space. 36 | 37 | |![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/linear.png)|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/circle.png)|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/panel.png)| 38 | |:--|:--|:--| 39 | |*linear*|*circle*|*panel*| 40 | 41 | **Please take a look at [main.dart](https://github.com/alnitak/flutter_star_menu/raw/master/example/lib/main.dart) and [main_more.dart](https://github.com/alnitak/flutter_star_menu/raw/master/example/lib/main_more.dart) in the example/lib dir for the examples.** 42 | 43 | 44 | Using the package is pretty simple: 45 | 46 | - install the package with `flutter pub add star_menu` 47 | - feed the `items` parameter with the menu entry widgets list 48 | - set the `params` with `StarMenuParameters` 49 | - set the `child` with a widget you wish to press to open the menu 50 | 51 | ```dart 52 | StarMenu( 53 | params: StarMenuParameters(), 54 | onStateChanged: (state) => print('State changed: $state'), 55 | onItemTapped: (index, controller) { 56 | // here you can programmatically close the menu 57 | if (index == 7) 58 | controller.closeMenu(); 59 | print('Menu item $index tapped'); 60 | }), 61 | items: entries, 62 | child: FloatingActionButton( 63 | onPressed: () {print('FloatingActionButton tapped');}, 64 | child: Icon(Icons.looks_one), 65 | ), 66 | ) 67 | ``` 68 | - `onStateChanged` triggers menu state canges: 69 | 70 | ``` 71 | enum MenuState { 72 | closed, 73 | closing, 74 | opening, 75 | open, 76 | } 77 | ``` 78 | 79 | - `items` parameter is used when entries are known. 80 | If you want to build items in runtime use `lazyItems`, 81 | ie when StarMenu is already builded in the widget tree, but the menu items changed: 82 | 83 | ```dart 84 | StarMenu( 85 | ... 86 | lazyItems: () async{ 87 | return [ 88 | Container( 89 | color: Color.fromARGB(255, Random().nextInt(255), 90 | Random().nextInt(255), Random().nextInt(255)), 91 | width: 60, 92 | height: 40, 93 | child: Text(userName), 94 | ), 95 | ... 96 | ]; 97 | } 98 | ) 99 | ``` 100 | `lazyItems` is a callback function which returns `Future>` which is called before opening the menu. 101 | Only `lazyItems` or `items` can be used. 102 | 103 | *StarMenu* can be created also with **addStarMenu()** widget extension: 104 | 105 | ```dart 106 | FloatingActionButton( 107 | onPressed: () {print('FloatingActionButton tapped');}, 108 | child: Icon(Icons.looks_one), 109 | ).addStarMenu( 110 | items: items, 111 | params: StarMenuParameters(), 112 | controller: controller, 113 | onItemTapped: (index, controller) {}), 114 | ``` 115 | 116 |
117 |
118 | 119 | ## ***Programmatically open menu*** 120 | There are two ways to programmatically open a menu, for example when pressing a button: 121 | 122 | - **if you already have a StarMenu in the tree, add [StarMenuController] to it:** 123 | ```dart 124 | StarMenuController starMenuController = StarMenuController(); 125 | 126 | StarMenu( 127 | params: StarMenuParameters(), 128 | controller: starMenuController, 129 | items: entries, 130 | child: ..., 131 | ) 132 | ``` 133 | then in your button: 134 | ```dart 135 | ElevatedButton( 136 | onPressed: () => starMenuController.openMenu!(), 137 | child: ..., 138 | ), 139 | ``` 140 | 141 | - **if you want to dinamically create a StartMenu for another widget, assign a GlobalKey to your widget:** 142 | ```dart 143 | GlobalKey containerKey = GlobalKey(); 144 | ... 145 | Container( 146 | key: containerKey, 147 | width: 40, 148 | height: 40, 149 | ), 150 | ``` 151 | then in your button call *StarMenuOverlay.displayStarMenu* with the widget context: 152 | ```dart 153 | ElevatedButton( 154 | onPressed: () { 155 | StarMenuOverlay.displayStarMenu( 156 | containerKey.currentContext!, 157 | StarMenu( 158 | params: StarMenuParameters(), 159 | items: entries, 160 | parentContext: containerKey.currentContext, 161 | ), 162 | ); 163 | }, 164 | child: ... 165 | ), 166 | ``` 167 | 168 | 169 | 170 | ### ***StarMenu*** 171 | Only [items] or [lazyItems] can be passed, not both. 172 | 173 | |Name|Type|Defaults|Description| 174 | |:-------|:----------|:----------|:-----------| 175 | |***params***|class|StarMenuParameters|See below.| 176 | |***items***|List?|-|Widget items entry list.| 177 | |***lazyItems***|Future> Function()?|-|Function to build dynamically items list whenever the menu open occurs.| 178 | |***child***|Widget|-|Widget that triggers the opening of the menu. Only [child] or [parentContext] is allowed| 179 | |***parentContext***|BuildContext|-|Widget that triggers the opening of the menu. Only [child] or [parentContext] is allowed| 180 | |***controller***|StarMenuController|-|context of the Widget where the menu will be opened. Only [child] or [parentContext] is allowed| 181 | |***onStateChanged***|Function(MenuState state)?|-|Return current menu state.| 182 | 183 | 184 | 185 | ### ***StarMenuParameters*** 186 | Class to define all the parameters for the shape, animation and menu behavior. 187 | 188 | |Name|Type|Defaults|Description| 189 | |:-------|:----------|:----------|:-----------| 190 | |***shape***|enum|MenuShape.circle|Menu shape kind. Could be [MenuShape.circle], [MenuShape.linear], [MenuShape.grid].| 191 | |***boundaryBackground***|class|-|See below.| 192 | |***linearShapeParams***|class|-|See below.| 193 | |***circleShapeParams***|class|-|See below.| 194 | |***gridShapeParams***|class|-|See below.| 195 | |***backgroundParams***|class|-|See below.| 196 | |***openDurationMs***|int|400|Open animation duration ms.| 197 | |***closeDurationMs***|int|150|Close animation duration ms.| 198 | |***rotateItemsAnimationAngle***|double|0.0|Starting rotation angle of the items that will reach 0 DEG when animation ends.| 199 | |***startItemScaleAnimation***|double|0.3|Starting scale of the items that will reach 1 when animation ends.| 200 | |***centerOffset***|Offset|Offset.zero|Shift offset of menu center from the center of parent widget.| 201 | |***useScreenCenter***|bool|false|Use the screen center instead of parent widget center.| 202 | |***useTouchAsCenter***|bool|false|Use the touch coordinate as the menu center.| 203 | |***checkItemsScreenBoundaries***|bool|false|Checks if the whole menu boundaries exceed screen edges, if so set it in place to be all visible.| 204 | |***checkMenuScreenBoundaries***|bool|true|Checks if items exceed screen edges, if so set them in place to be visible.| 205 | |***animationCurve***|Curve|Curves.fastOutSlowIn|Animation curve kind to use.| 206 | |***useLongPress***|bool|false|Use long press instead of a tap to open the menu.| 207 | |***longPressDuration***|Duration|500 ms|The timing to trigger long press.| 208 | |***onHoverScale***|double|1.0|Scale item when mouse is hover (desktop only)| 209 | 210 | 211 | 212 | There are some ***StarMenuParameters*** factory presets with which you can set *StarMenu.params* 213 | 214 | ||| 215 | |:-------|:----------| 216 | |*StarMenuParameters.dropdown(BuildContext context)*|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/dropdown.png)| 217 | |*StarMenuParameters.panel(BuildContext context, {int columns = 3})*|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/panel.png)| 218 | 219 | *StarMenuParameters.arc(BuildContext context, ArcType type, {double radiusX = 130, double radiusY = 130})* 220 | 221 | |type|result| 222 | |:-------|:----------| 223 | |ArcType.semiUp|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/semiUp.png)| 224 | |ArcType.semiDown|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/semiDown.png)| 225 | |ArcType.semiLeft|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/semiL.png)| 226 | |ArcType.semiRight|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/semiR.png)| 227 | |ArcType.quarterTopRight|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/quarterTopR.png)| 228 | |ArcType.quarterTopLeft|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/quarterTopL.png)| 229 | |ArcType.quarterBottomRight|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/quarterBottomR.png)| 230 | |ArcType.quarterBottomLeft|![Image](https://github.com/alnitak/flutter_star_menu/raw/master/images/quarterBottomL.png)| 231 | 232 | 233 | 234 | --- 235 | 236 | 237 | 238 | ### ***BoundaryBackground*** 239 | 240 | |Name|Type|Defaults|Description| 241 | |:-------|:----------|:----------|:-----------| 242 | |***color***|Color|0x80000000|color of the boundary background.| 243 | |***padding***|EdgeInsets|EdgeInsets.all(8.0)|Padding of the boundary background.| 244 | |***decoration***|Decoration|BorderRadius.circular(8)| background Container widget decoration.| 245 | |***blurSigmaX***|double|0.0| horizontal blur of the boundary background.| 246 | |***blurSigmaY***|double|0.0| vertical blur of the boundary background.| 247 | 248 | --- 249 | 250 | 251 | 252 | ### ***LinearShapeParams*** 253 | 254 | |Name|Type|Defaults|Description| 255 | |:-------|:----------|:----------|:-----------| 256 | |***angle***|double|90.0|Degree angle. Anticlockwise with 0° on 3 o'clock.| 257 | |***space***|double|0.0|Space between items.| 258 | |***alignment***|LinearAlignment|center| *left*, *center*, *right*, *top*, *bottom*. Useful when the linear shape is vertical or horizontal.| 259 | 260 | --- 261 | 262 | 263 | ### ***CircleShapeParams*** 264 | 265 | |Name|Type|Defaults|Description| 266 | |:-------|:----------|:----------|:-----------| 267 | |***radiusX***|double|100.0|Horizontal radius.| 268 | |***radiusY***|double|100.0|Vertical radius.| 269 | |***startAngle***|double|0.0|Starting angle for the 1st item. Anticlockwise with 0° on the right.| 270 | |***endAngle***|double|360.0|Ending angle for the 1st item. Anticlockwise with 0° on the right.| 271 | 272 | --- 273 | 274 | 275 | 276 | ### ***GridShapeParams*** 277 | 278 | |Name|Type|Defaults|Description| 279 | |:-------|:----------|:----------|:-----------| 280 | |***columns***|int|3|Number of columns.| 281 | |***columnsSpaceH***|int|0|Horizontal space between items.| 282 | |***columnsSpaceV***|int|0|Vertical space between items.| 283 | 284 | --- 285 | 286 | 287 | ### ***BackgroundParams*** 288 | 289 | |Name|Type|Defaults|Description| 290 | |:-------|:----------|:----------|:-----------| 291 | |***animatedBlur***|bool|false|Animate background blur from 0.0 to sigma if true.| 292 | |***sigmaX***|double|0.0|Horizontal blur.| 293 | |***sigmaY***|double|0.0|Vertical blur.| 294 | |***animatedBackgroundColor***|bool|false|If true animate from transparent to [backgroundColor].| 295 | |***backgroundColor***|Color|Colors.transparent|Background color.| 296 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:star_menu/star_menu.dart'; 3 | 4 | void main() { 5 | runApp(const MyApp()); 6 | } 7 | 8 | class MyApp extends StatelessWidget { 9 | const MyApp({super.key}); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return MaterialApp( 14 | debugShowCheckedModeBanner: false, 15 | title: 'StarMenu Demo', 16 | home: const MyHomePage(), 17 | theme: ThemeData(useMaterial3: false), 18 | ); 19 | } 20 | } 21 | 22 | class MyHomePage extends StatelessWidget { 23 | const MyHomePage({super.key}); 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | final backgroundStarMenuController = StarMenuController(); 28 | final centerStarMenuController = StarMenuController(); 29 | final sliderValue = ValueNotifier(0.5); 30 | final containerKey = GlobalKey(); 31 | 32 | // entries for the dropdown menu 33 | final upperMenuItems = [ 34 | const Text('menu entry 1'), 35 | const Text('menu entry 2'), 36 | const Text('menu entry 3'), 37 | const Text('menu entry 4'), 38 | const Text('menu entry 5'), 39 | const Text('menu entry 6'), 40 | ]; 41 | 42 | // other entries 43 | // Every items may have a sub-menu. 44 | // Here the sub-menus are added with [addStarMenu] extension 45 | final otherEntries = [ 46 | const FloatingActionButton( 47 | onPressed: null, 48 | backgroundColor: Colors.black, 49 | child: Icon(Icons.add_call), 50 | ).addStarMenu( 51 | items: upperMenuItems, 52 | params: StarMenuParameters.dropdown(context), 53 | ), 54 | const FloatingActionButton( 55 | onPressed: null, 56 | backgroundColor: Colors.indigo, 57 | child: Icon(Icons.adb), 58 | ).addStarMenu( 59 | items: upperMenuItems, 60 | params: StarMenuParameters.dropdown(context), 61 | ), 62 | const FloatingActionButton( 63 | onPressed: null, 64 | backgroundColor: Colors.purple, 65 | child: Icon(Icons.home), 66 | ).addStarMenu( 67 | items: upperMenuItems, 68 | params: StarMenuParameters.dropdown(context), 69 | ), 70 | const FloatingActionButton( 71 | onPressed: null, 72 | backgroundColor: Colors.blueGrey, 73 | child: Icon(Icons.delete), 74 | ).addStarMenu( 75 | items: upperMenuItems, 76 | params: StarMenuParameters.dropdown(context), 77 | ), 78 | const FloatingActionButton( 79 | onPressed: null, 80 | backgroundColor: Colors.deepPurple, 81 | child: Icon(Icons.get_app), 82 | ).addStarMenu( 83 | items: upperMenuItems, 84 | params: StarMenuParameters.dropdown(context), 85 | ), 86 | ]; 87 | 88 | // bottom left menu entries 89 | final chipsEntries = [ 90 | const Chip( 91 | avatar: CircleAvatar(child: Text('SM')), 92 | label: Text('of widgets'), 93 | ), 94 | const Chip( 95 | avatar: CircleAvatar(child: Text('SM')), 96 | label: Text('any kind'), 97 | ), 98 | const Chip( 99 | avatar: CircleAvatar(child: Text('SM')), 100 | label: Text('almost'), 101 | ), 102 | const Chip( 103 | avatar: CircleAvatar(child: Text('SM')), 104 | label: Text('can be'), 105 | ), 106 | const Chip( 107 | avatar: CircleAvatar(child: Text('SM')), 108 | label: Text('entries'), 109 | ), 110 | const Chip( 111 | avatar: CircleAvatar(child: Text('SM')), 112 | label: Text('The menu'), 113 | ), 114 | ]; 115 | 116 | return Scaffold( 117 | resizeToAvoidBottomInset: false, 118 | appBar: AppBar( 119 | title: const Text('StarMenu demo'), 120 | actions: [ 121 | // upper bar menu 122 | StarMenu( 123 | params: StarMenuParameters.dropdown(context).copyWith( 124 | backgroundParams: const BackgroundParams().copyWith( 125 | sigmaX: 3, 126 | sigmaY: 3, 127 | ), 128 | ), 129 | items: upperMenuItems, 130 | onItemTapped: (index, c) { 131 | debugPrint('Item $index tapped'); 132 | c.closeMenu!(); 133 | }, 134 | child: const Padding( 135 | padding: EdgeInsets.all(18), 136 | child: Icon(Icons.menu), 137 | ), 138 | ), 139 | ], 140 | ), 141 | body: Padding( 142 | padding: const EdgeInsets.all(8), 143 | child: Stack( 144 | children: [ 145 | /// add a menu to the background 146 | Container( 147 | width: double.infinity, 148 | height: double.infinity, 149 | color: Colors.white, 150 | ).addStarMenu( 151 | items: upperMenuItems, 152 | params: StarMenuParameters.dropdown(context).copyWith( 153 | useTouchAsCenter: true, 154 | ), 155 | controller: backgroundStarMenuController, 156 | ), 157 | 158 | Align( 159 | child: Container( 160 | width: 1, 161 | height: double.maxFinite, 162 | color: Colors.black45, 163 | ), 164 | ), 165 | Align( 166 | child: Container( 167 | width: double.maxFinite, 168 | height: 1, 169 | color: Colors.black45, 170 | ), 171 | ), 172 | 173 | // background 174 | const Align( 175 | alignment: Alignment.topCenter, 176 | child: Text( 177 | 'Touch the background to open the menu ' 178 | 'at the coordinates you touched', 179 | textAlign: TextAlign.center, 180 | ), 181 | ), 182 | 183 | // center menu with default [StarMenuParameters] parameters 184 | Align( 185 | child: StarMenu( 186 | controller: centerStarMenuController, 187 | items: otherEntries, 188 | child: const FloatingActionButton( 189 | onPressed: null, 190 | mini: true, 191 | backgroundColor: Colors.blue, 192 | child: Icon(Icons.add), 193 | ), 194 | ), 195 | ), 196 | 197 | // center right menu. 198 | Align( 199 | alignment: Alignment.centerRight, 200 | child: StarMenu( 201 | params: StarMenuParameters.arc( 202 | ArcType.semiLeft, 203 | radiusX: 100, 204 | radiusY: 180, 205 | ), 206 | items: otherEntries, 207 | child: const FloatingActionButton( 208 | onPressed: null, 209 | child: Icon(Icons.home_work_outlined), 210 | ), 211 | ), 212 | ), 213 | 214 | // bottom right panel menu 215 | Align( 216 | alignment: Alignment.bottomRight, 217 | child: StarMenu( 218 | params: StarMenuParameters.panel( 219 | context, 220 | columns: 3, 221 | ).copyWith(centerOffset: const Offset(-150, -150)), 222 | items: [ 223 | const IconMenu(icon: Icons.skip_previous, text: 'previous'), 224 | const IconMenu(icon: Icons.play_arrow, text: 'play'), 225 | const IconMenu(icon: Icons.skip_next, text: 'next'), 226 | const IconMenu(icon: Icons.album, text: 'album'), 227 | const IconMenu(icon: Icons.alarm, text: 'alarm'), 228 | const IconMenu(icon: Icons.info_outline, text: 'info'), 229 | SizedBox( 230 | width: 180, 231 | height: 20, 232 | child: ValueListenableBuilder( 233 | valueListenable: sliderValue, 234 | builder: (_, v, __) { 235 | return Slider( 236 | value: v, 237 | onChanged: (value) { 238 | sliderValue.value = value; 239 | }, 240 | ); 241 | }, 242 | ), 243 | ), 244 | ], 245 | child: const FloatingActionButton( 246 | onPressed: null, 247 | child: Icon(Icons.grid_view), 248 | ), 249 | ), 250 | ), 251 | 252 | // bottom left linear menu 253 | Align( 254 | alignment: Alignment.bottomLeft, 255 | child: StarMenu( 256 | params: const StarMenuParameters( 257 | shape: MenuShape.linear, 258 | linearShapeParams: LinearShapeParams( 259 | angle: 90, 260 | alignment: LinearAlignment.left, 261 | space: 15, 262 | ), 263 | animationCurve: Curves.easeOutCubic, 264 | centerOffset: Offset(50, -50), 265 | openDurationMs: 150, 266 | ), 267 | items: chipsEntries, 268 | parentContext: containerKey.currentContext, 269 | child: const FloatingActionButton( 270 | onPressed: null, 271 | child: Icon(Icons.view_stream_rounded), 272 | ), 273 | ), 274 | ), 275 | 276 | // a generic Widget with its key defined. 277 | // This key will be used to show the menu with an event 278 | // like pressing a button 279 | Align( 280 | alignment: const Alignment(0, -0.4), 281 | child: Container( 282 | key: containerKey, 283 | width: 40, 284 | height: 40, 285 | decoration: BoxDecoration( 286 | color: Colors.amber, 287 | borderRadius: const BorderRadius.all( 288 | Radius.circular(40), 289 | ), 290 | border: Border.all( 291 | width: 2, 292 | color: Colors.black, 293 | style: BorderStyle.solid, 294 | ), 295 | ), 296 | ), 297 | ), 298 | 299 | // open centered menu programmatically 300 | Align( 301 | alignment: Alignment.bottomCenter, 302 | child: Column( 303 | mainAxisSize: MainAxisSize.min, 304 | children: [ 305 | // programmatically open the menu using StartMenu controller 306 | ElevatedButton( 307 | onPressed: () => centerStarMenuController.openMenu!(), 308 | child: const Text( 309 | 'Open centered menu\nprogrammatically\nwith controller', 310 | textAlign: TextAlign.center, 311 | ), 312 | ), 313 | const SizedBox(height: 20), 314 | // programmatically open the menu using 315 | // a key of a widget 316 | ElevatedButton( 317 | onPressed: () { 318 | StarMenuOverlay.displayStarMenu( 319 | containerKey.currentContext!, 320 | StarMenu( 321 | items: otherEntries, 322 | parentContext: containerKey.currentContext, 323 | ), 324 | ); 325 | }, 326 | child: const Text( 327 | 'Open menu\nprogrammatically\nwith a Widget key', 328 | textAlign: TextAlign.center, 329 | ), 330 | ), 331 | ], 332 | ), 333 | ), 334 | ], 335 | ), 336 | ), 337 | ); 338 | } 339 | } 340 | 341 | class IconMenu extends StatelessWidget { 342 | const IconMenu({ 343 | required this.icon, 344 | required this.text, 345 | super.key, 346 | }); 347 | 348 | final IconData icon; 349 | final String text; 350 | 351 | @override 352 | Widget build(BuildContext context) { 353 | return Column( 354 | mainAxisSize: MainAxisSize.min, 355 | children: [ 356 | Icon(icon, size: 32), 357 | const SizedBox(height: 6), 358 | Text(text), 359 | ], 360 | ); 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /example/lib/main_more.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:star_menu/star_menu.dart'; 6 | import 'package:star_menu_example/submenu_card.dart'; 7 | 8 | void main() { 9 | runApp(const MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | const MyApp({super.key}); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | title: 'StarMenu Demo', 19 | scrollBehavior: const MaterialScrollBehavior().copyWith( 20 | // enable mouse dragging on desktop 21 | dragDevices: PointerDeviceKind.values.toSet(), 22 | ), 23 | theme: ThemeData(useMaterial3: false), 24 | home: const MyHomePage(), 25 | ); 26 | } 27 | } 28 | 29 | class MyHomePage extends StatefulWidget { 30 | const MyHomePage({super.key}); 31 | 32 | @override 33 | MyHomePageState createState() => MyHomePageState(); 34 | } 35 | 36 | class MyHomePageState extends State { 37 | late List entries; 38 | late List subEntries; 39 | 40 | @override 41 | void initState() { 42 | super.initState(); 43 | subEntries = subMenuEntries(); 44 | entries = menuEntries(); 45 | } 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return Scaffold( 50 | appBar: AppBar( 51 | title: const Text('StarMenu demo'), 52 | ), 53 | body: Stack( 54 | children: [ 55 | Center( 56 | // Scroll view to test the item centers are always 57 | // computed even if its position changes 58 | child: SingleChildScrollView( 59 | child: SizedBox( 60 | height: 1000, 61 | child: Column( 62 | mainAxisAlignment: MainAxisAlignment.center, 63 | children: [ 64 | const SizedBox(height: 20), 65 | const Text('Load items at runtime'), 66 | 67 | // LAZY MENU 68 | StarMenu( 69 | onStateChanged: (state) { 70 | debugPrint('State changed: $state'); 71 | }, 72 | params: const StarMenuParameters( 73 | shape: MenuShape.linear, 74 | linearShapeParams: LinearShapeParams( 75 | angle: 270, 76 | space: 30, 77 | ), 78 | ), 79 | 80 | onItemTapped: (index, controller) { 81 | // don't close if the item tapped is not the ListView 82 | if (index != 1) controller.closeMenu!(); 83 | }, 84 | // lazyItemsLoad let you build menu entries at runtime 85 | lazyItems: () async { 86 | return [ 87 | Container( 88 | color: Color.fromARGB( 89 | 255, 90 | Random().nextInt(255), 91 | Random().nextInt(255), 92 | Random().nextInt(255), 93 | ), 94 | width: 100, 95 | height: 40, 96 | ), 97 | SizedBox( 98 | width: 150, 99 | height: 230, 100 | child: Card( 101 | elevation: 6, 102 | margin: const EdgeInsets.all(6), 103 | child: ListView( 104 | children: [ 105 | 'the', 106 | 'menu', 107 | 'entries', 108 | 'can', 109 | 'be', 110 | 'almost', 111 | 'any', 112 | 'kind', 113 | 'of', 114 | 'widgets', 115 | ].map((s) { 116 | return Card( 117 | margin: const EdgeInsets.all(10), 118 | child: Text( 119 | s, 120 | textAlign: TextAlign.center, 121 | ), 122 | ); 123 | }).toList(), 124 | ), 125 | ), 126 | ), 127 | ]; 128 | }, 129 | child: FloatingActionButton( 130 | onPressed: () { 131 | debugPrint('FloatingActionButton Menu1 tapped'); 132 | }, 133 | child: const Icon(Icons.looks_one), 134 | ), 135 | ), 136 | 137 | const SizedBox(height: 40), 138 | const Text('Colored and blurred background'), 139 | 140 | // LINEAR MENU 141 | StarMenu( 142 | params: StarMenuParameters( 143 | shape: MenuShape.linear, 144 | onHoverScale: 1.3, 145 | linearShapeParams: const LinearShapeParams( 146 | angle: 270, 147 | space: 10, 148 | alignment: LinearAlignment.center, 149 | ), 150 | boundaryBackground: BoundaryBackground(), 151 | backgroundParams: BackgroundParams( 152 | backgroundColor: Colors.blue.withOpacity(0.2), 153 | animatedBackgroundColor: false, 154 | animatedBlur: false, 155 | sigmaX: 10, 156 | sigmaY: 10, 157 | ), 158 | ), 159 | onItemTapped: (index, controller) { 160 | if (index == 7) controller.closeMenu!(); 161 | }, 162 | items: entries, 163 | child: FloatingActionButton( 164 | onPressed: () { 165 | debugPrint('FloatingActionButton Menu1 tapped'); 166 | }, 167 | child: const Icon(Icons.looks_two), 168 | ), 169 | ), 170 | 171 | const SizedBox(height: 40), 172 | const Text('Animated blur background'), 173 | 174 | // CIRCLE MENU 175 | // it's possible to use the extension addStarMenu() 176 | // with all Widgets 177 | FloatingActionButton( 178 | onPressed: () { 179 | debugPrint('FloatingActionButton Menu2 tapped'); 180 | }, 181 | backgroundColor: Colors.red, 182 | child: const Icon(Icons.looks_3), 183 | ).addStarMenu( 184 | items: entries, 185 | params: const StarMenuParameters( 186 | backgroundParams: BackgroundParams( 187 | animatedBlur: true, 188 | sigmaX: 4, 189 | sigmaY: 4, 190 | backgroundColor: Colors.transparent, 191 | ), 192 | circleShapeParams: CircleShapeParams(radiusY: 280), 193 | openDurationMs: 1000, 194 | rotateItemsAnimationAngle: 360, 195 | ), 196 | onItemTapped: (index, controller) { 197 | if (index == 7) controller.closeMenu!(); 198 | }, 199 | ), 200 | 201 | const SizedBox(height: 40), 202 | const Text('Animated color background'), 203 | 204 | // GRID MENU 205 | StarMenu( 206 | params: StarMenuParameters( 207 | shape: MenuShape.grid, 208 | openDurationMs: 1200, 209 | gridShapeParams: const GridShapeParams( 210 | columns: 3, 211 | columnsSpaceH: 6, 212 | columnsSpaceV: 6, 213 | ), 214 | backgroundParams: BackgroundParams( 215 | sigmaX: 0, 216 | sigmaY: 0, 217 | animatedBackgroundColor: true, 218 | backgroundColor: Colors.black.withOpacity(0.4), 219 | ), 220 | ), 221 | onItemTapped: (index, controller) { 222 | if (index == 7) controller.closeMenu!(); 223 | }, 224 | items: entries, 225 | child: FloatingActionButton( 226 | onPressed: () { 227 | debugPrint('FloatingActionButton Menu3 tapped'); 228 | }, 229 | backgroundColor: Colors.black, 230 | child: const Icon(Icons.looks_4), 231 | ), 232 | ), 233 | ], 234 | ), 235 | ), 236 | ), 237 | ), 238 | ], 239 | ), 240 | ); 241 | } 242 | 243 | // Build the list of menu entries 244 | List menuEntries() { 245 | final sliderValue = ValueNotifier(0.5); 246 | return [ 247 | const SubMenuCard( 248 | width: 100, 249 | text: 'Linear, check whole menu boundaries', 250 | ).addStarMenu( 251 | items: subEntries, 252 | params: const StarMenuParameters( 253 | shape: MenuShape.linear, 254 | linearShapeParams: LinearShapeParams( 255 | angle: 120, 256 | space: 15, 257 | ), 258 | checkMenuScreenBoundaries: true, 259 | ), 260 | ), 261 | const SubMenuCard( 262 | width: 70, 263 | text: 'Linear, centered items', 264 | ).addStarMenu( 265 | items: subEntries, 266 | params: const StarMenuParameters( 267 | shape: MenuShape.linear, 268 | linearShapeParams: LinearShapeParams( 269 | angle: 90, 270 | space: 15, 271 | alignment: LinearAlignment.center, 272 | ), 273 | ), 274 | ), 275 | const SubMenuCard( 276 | width: 70, 277 | text: 'Linear, check items boundaries', 278 | ).addStarMenu( 279 | items: subEntries, 280 | params: const StarMenuParameters( 281 | shape: MenuShape.linear, 282 | linearShapeParams: LinearShapeParams( 283 | angle: 60, 284 | space: 15, 285 | ), 286 | checkItemsScreenBoundaries: true, 287 | checkMenuScreenBoundaries: false, 288 | ), 289 | ), 290 | const SubMenuCard( 291 | width: 70, 292 | text: 'Linear, left aligned', 293 | ).addStarMenu( 294 | items: subEntries, 295 | params: const StarMenuParameters( 296 | shape: MenuShape.linear, 297 | linearShapeParams: LinearShapeParams( 298 | angle: 90, 299 | space: 15, 300 | alignment: LinearAlignment.left, 301 | ), 302 | ), 303 | ), 304 | const SubMenuCard( 305 | width: 60, 306 | text: 'Centered circle', 307 | ).addStarMenu( 308 | items: subEntries, 309 | params: const StarMenuParameters( 310 | shape: MenuShape.circle, 311 | useScreenCenter: true, 312 | ), 313 | ), 314 | const SubMenuCard( 315 | width: 70, 316 | text: 'Linear, right aligned', 317 | ).addStarMenu( 318 | items: subEntries, 319 | params: const StarMenuParameters( 320 | shape: MenuShape.linear, 321 | linearShapeParams: LinearShapeParams( 322 | angle: 90, 323 | space: 0, 324 | alignment: LinearAlignment.right, 325 | ), 326 | ), 327 | ), 328 | SizedBox( 329 | width: 180, 330 | height: 20, 331 | child: ValueListenableBuilder( 332 | valueListenable: sliderValue, 333 | builder: (_, v, __) { 334 | return Slider( 335 | value: v, 336 | onChanged: (value) { 337 | sliderValue.value = value; 338 | }, 339 | ); 340 | }, 341 | ), 342 | ), 343 | FloatingActionButton(child: const Text('close'), onPressed: () {}), 344 | ]; 345 | } 346 | 347 | // Build the list of sub-menu entries 348 | List subMenuEntries() { 349 | return [ 350 | const Chip( 351 | avatar: CircleAvatar( 352 | child: Text('SM'), 353 | ), 354 | label: Text('of widgets'), 355 | ), 356 | const Chip( 357 | avatar: CircleAvatar( 358 | child: Text('SM'), 359 | ), 360 | label: Text('any kind'), 361 | ), 362 | const Chip( 363 | avatar: CircleAvatar( 364 | child: Text('SM'), 365 | ), 366 | label: Text('almost'), 367 | ), 368 | const Chip( 369 | avatar: CircleAvatar( 370 | child: Text('SM'), 371 | ), 372 | label: Text('can be'), 373 | ), 374 | const Chip( 375 | avatar: CircleAvatar( 376 | child: Text('SM'), 377 | ), 378 | label: Text('The menu entries'), 379 | ), 380 | ]; 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1020; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | INFOPLIST_FILE = Runner/Info.plist; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 294 | PRODUCT_BUNDLE_IDENTIFIER = com.bavagnoli.starMenuExample; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 297 | SWIFT_VERSION = 5.0; 298 | VERSIONING_SYSTEM = "apple-generic"; 299 | }; 300 | name = Profile; 301 | }; 302 | 97C147031CF9000F007C117D /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 308 | CLANG_CXX_LIBRARY = "libc++"; 309 | CLANG_ENABLE_MODULES = YES; 310 | CLANG_ENABLE_OBJC_ARC = YES; 311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 312 | CLANG_WARN_BOOL_CONVERSION = YES; 313 | CLANG_WARN_COMMA = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN_ENUM_CONVERSION = YES; 319 | CLANG_WARN_INFINITE_RECURSION = YES; 320 | CLANG_WARN_INT_CONVERSION = YES; 321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 326 | CLANG_WARN_STRICT_PROTOTYPES = YES; 327 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 328 | CLANG_WARN_UNREACHABLE_CODE = YES; 329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 331 | COPY_PHASE_STRIP = NO; 332 | DEBUG_INFORMATION_FORMAT = dwarf; 333 | ENABLE_STRICT_OBJC_MSGSEND = YES; 334 | ENABLE_TESTABILITY = YES; 335 | GCC_C_LANGUAGE_STANDARD = gnu99; 336 | GCC_DYNAMIC_NO_PIC = NO; 337 | GCC_NO_COMMON_BLOCKS = YES; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_PREPROCESSOR_DEFINITIONS = ( 340 | "DEBUG=1", 341 | "$(inherited)", 342 | ); 343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 345 | GCC_WARN_UNDECLARED_SELECTOR = YES; 346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 347 | GCC_WARN_UNUSED_FUNCTION = YES; 348 | GCC_WARN_UNUSED_VARIABLE = YES; 349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 350 | MTL_ENABLE_DEBUG_INFO = YES; 351 | ONLY_ACTIVE_ARCH = YES; 352 | SDKROOT = iphoneos; 353 | TARGETED_DEVICE_FAMILY = "1,2"; 354 | }; 355 | name = Debug; 356 | }; 357 | 97C147041CF9000F007C117D /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ALWAYS_SEARCH_USER_PATHS = NO; 361 | CLANG_ANALYZER_NONNULL = YES; 362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 363 | CLANG_CXX_LIBRARY = "libc++"; 364 | CLANG_ENABLE_MODULES = YES; 365 | CLANG_ENABLE_OBJC_ARC = YES; 366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_COMMA = YES; 369 | CLANG_WARN_CONSTANT_CONVERSION = YES; 370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 372 | CLANG_WARN_EMPTY_BODY = YES; 373 | CLANG_WARN_ENUM_CONVERSION = YES; 374 | CLANG_WARN_INFINITE_RECURSION = YES; 375 | CLANG_WARN_INT_CONVERSION = YES; 376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 381 | CLANG_WARN_STRICT_PROTOTYPES = YES; 382 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 383 | CLANG_WARN_UNREACHABLE_CODE = YES; 384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 386 | COPY_PHASE_STRIP = NO; 387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 388 | ENABLE_NS_ASSERTIONS = NO; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | GCC_C_LANGUAGE_STANDARD = gnu99; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 394 | GCC_WARN_UNDECLARED_SELECTOR = YES; 395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 396 | GCC_WARN_UNUSED_FUNCTION = YES; 397 | GCC_WARN_UNUSED_VARIABLE = YES; 398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 399 | MTL_ENABLE_DEBUG_INFO = NO; 400 | SDKROOT = iphoneos; 401 | SUPPORTED_PLATFORMS = iphoneos; 402 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 403 | TARGETED_DEVICE_FAMILY = "1,2"; 404 | VALIDATE_PRODUCT = YES; 405 | }; 406 | name = Release; 407 | }; 408 | 97C147061CF9000F007C117D /* Debug */ = { 409 | isa = XCBuildConfiguration; 410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 411 | buildSettings = { 412 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 413 | CLANG_ENABLE_MODULES = YES; 414 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 415 | ENABLE_BITCODE = NO; 416 | INFOPLIST_FILE = Runner/Info.plist; 417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 418 | PRODUCT_BUNDLE_IDENTIFIER = com.bavagnoli.starMenuExample; 419 | PRODUCT_NAME = "$(TARGET_NAME)"; 420 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 421 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 422 | SWIFT_VERSION = 5.0; 423 | VERSIONING_SYSTEM = "apple-generic"; 424 | }; 425 | name = Debug; 426 | }; 427 | 97C147071CF9000F007C117D /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 430 | buildSettings = { 431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 432 | CLANG_ENABLE_MODULES = YES; 433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 434 | ENABLE_BITCODE = NO; 435 | INFOPLIST_FILE = Runner/Info.plist; 436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 437 | PRODUCT_BUNDLE_IDENTIFIER = com.bavagnoli.starMenuExample; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 440 | SWIFT_VERSION = 5.0; 441 | VERSIONING_SYSTEM = "apple-generic"; 442 | }; 443 | name = Release; 444 | }; 445 | /* End XCBuildConfiguration section */ 446 | 447 | /* Begin XCConfigurationList section */ 448 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 449 | isa = XCConfigurationList; 450 | buildConfigurations = ( 451 | 97C147031CF9000F007C117D /* Debug */, 452 | 97C147041CF9000F007C117D /* Release */, 453 | 249021D3217E4FDB00AE95B9 /* Profile */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 97C147061CF9000F007C117D /* Debug */, 462 | 97C147071CF9000F007C117D /* Release */, 463 | 249021D4217E4FDB00AE95B9 /* Profile */, 464 | ); 465 | defaultConfigurationIsVisible = 0; 466 | defaultConfigurationName = Release; 467 | }; 468 | /* End XCConfigurationList section */ 469 | }; 470 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 471 | } 472 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 28 | 29 | 30 | 31 | {@tool 32 | sampl 33 | backgroundColor 34 | animationColor 35 | BACKGROUNDIMAGE 36 | 37 | 38 | 39 | 45 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 72 | 73 | 74 | 76 | 77 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 137 | 138 | 139 | 140 | 141 | 142 | 145 | { 146 | "keyToString": { 147 | "RunOnceActivity.cidr.known.project.marker": "true", 148 | "cidr.known.project.marker": "true", 149 | "dart.analysis.tool.window.visible": "false", 150 | "io.flutter.reload.alreadyRun": "true", 151 | "last_opened_file_path": "/home/deimos/Documents/workspace/FLUTTER/selenium4/libs/star_menu", 152 | "show.migrate.to.gradle.popup": "false" 153 | } 154 | } 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 168 | 169 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 1553984604144 185 | 189 | 190 | 1554037113600 191 | 196 | 197 | 1554037835144 198 | 203 | 204 | 1554037930115 205 | 210 | 211 | 1554040607805 212 | 217 | 218 | 1554042151304 219 | 224 | 225 | 1554046598749 226 | 231 | 232 | 1560371544290 233 | 238 | 239 | 1628621700227 240 | 245 | 246 | 1628627499501 247 | 252 | 253 | 1628628835637 254 | 259 | 260 | 1629667585100 261 | 266 | 267 | 1635511783138 268 | 273 | 274 | 1636579654967 275 | 280 | 281 | 1647117898999 282 | 287 | 288 | 1647118489817 289 | 294 | 295 | 1647159453058 296 | 301 | 302 | 1658580839060 303 | 308 | 309 | 1658597778635 310 | 315 | 316 | 1663924436397 317 | 322 | 323 | 1663924789733 324 | 329 | 330 | 1663925412375 331 | 336 | 337 | 1663925736314 338 | 343 | 344 | 1663930691675 345 | 350 | 351 | 1663933180447 352 | 357 | 358 | 1663934123075 359 | 364 | 365 | 1670865323748 366 | 371 | 372 | 1671797430290 373 | 378 | 379 | 1675638118785 380 | 385 | 386 | 1676840356616 387 | 392 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 438 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | --------------------------------------------------------------------------------