├── 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 |
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 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
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 | [](https://pub.dev/packages/star_menu)
8 | 
9 | 
10 | 
11 | 
12 | 
13 | 
14 | 
15 |
16 | [pub.dev link](https://pub.dev/packages/star_menu)
17 |
18 | 
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 | 
28 | 
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 | ||||
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)*||
217 | |*StarMenuParameters.panel(BuildContext context, {int columns = 3})*||
218 |
219 | *StarMenuParameters.arc(BuildContext context, ArcType type, {double radiusX = 130, double radiusY = 130})*
220 |
221 | |type|result|
222 | |:-------|:----------|
223 | |ArcType.semiUp||
224 | |ArcType.semiDown||
225 | |ArcType.semiLeft||
226 | |ArcType.semiRight||
227 | |ArcType.quarterTopRight||
228 | |ArcType.quarterTopLeft||
229 | |ArcType.quarterBottomRight||
230 | |ArcType.quarterBottomLeft||
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 |
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 | {@tool
32 | sampl
33 | backgroundColor
34 | animationColor
35 | BACKGROUNDIMAGE
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
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 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
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 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | 1553984604144
185 |
186 |
187 | 1553984604144
188 |
189 |
190 | 1554037113600
191 |
192 |
193 |
194 | 1554037113600
195 |
196 |
197 | 1554037835144
198 |
199 |
200 |
201 | 1554037835144
202 |
203 |
204 | 1554037930115
205 |
206 |
207 |
208 | 1554037930115
209 |
210 |
211 | 1554040607805
212 |
213 |
214 |
215 | 1554040607805
216 |
217 |
218 | 1554042151304
219 |
220 |
221 |
222 | 1554042151304
223 |
224 |
225 | 1554046598749
226 |
227 |
228 |
229 | 1554046598749
230 |
231 |
232 | 1560371544290
233 |
234 |
235 |
236 | 1560371544291
237 |
238 |
239 | 1628621700227
240 |
241 |
242 |
243 | 1628621700229
244 |
245 |
246 | 1628627499501
247 |
248 |
249 |
250 | 1628627499501
251 |
252 |
253 | 1628628835637
254 |
255 |
256 |
257 | 1628628835637
258 |
259 |
260 | 1629667585100
261 |
262 |
263 |
264 | 1629667585100
265 |
266 |
267 | 1635511783138
268 |
269 |
270 |
271 | 1635511783138
272 |
273 |
274 | 1636579654967
275 |
276 |
277 |
278 | 1636579654967
279 |
280 |
281 | 1647117898999
282 |
283 |
284 |
285 | 1647117898999
286 |
287 |
288 | 1647118489817
289 |
290 |
291 |
292 | 1647118489817
293 |
294 |
295 | 1647159453058
296 |
297 |
298 |
299 | 1647159453058
300 |
301 |
302 | 1658580839060
303 |
304 |
305 |
306 | 1658580839060
307 |
308 |
309 | 1658597778635
310 |
311 |
312 |
313 | 1658597778635
314 |
315 |
316 | 1663924436397
317 |
318 |
319 |
320 | 1663924436397
321 |
322 |
323 | 1663924789733
324 |
325 |
326 |
327 | 1663924789733
328 |
329 |
330 | 1663925412375
331 |
332 |
333 |
334 | 1663925412375
335 |
336 |
337 | 1663925736314
338 |
339 |
340 |
341 | 1663925736314
342 |
343 |
344 | 1663930691675
345 |
346 |
347 |
348 | 1663930691675
349 |
350 |
351 | 1663933180447
352 |
353 |
354 |
355 | 1663933180447
356 |
357 |
358 | 1663934123075
359 |
360 |
361 |
362 | 1663934123075
363 |
364 |
365 | 1670865323748
366 |
367 |
368 |
369 | 1670865323748
370 |
371 |
372 | 1671797430290
373 |
374 |
375 |
376 | 1671797430290
377 |
378 |
379 | 1675638118785
380 |
381 |
382 |
383 | 1675638118785
384 |
385 |
386 | 1676840356616
387 |
388 |
389 |
390 | 1676840356616
391 |
392 |
393 |
394 |
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 |
430 |
437 |
438 |
439 |
451 |
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 |
479 |
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 |
--------------------------------------------------------------------------------