├── .fvmrc ├── example ├── web │ ├── CNAME │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── manifest.json │ └── index.html ├── 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 │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── RunnerTests │ │ └── RunnerTests.swift │ └── .gitignore ├── macos │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_512.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Release.entitlements │ │ ├── DebugProfile.entitlements │ │ ├── MainFlutterWindow.swift │ │ └── Info.plist │ ├── .gitignore │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── RunnerTests │ │ └── RunnerTests.swift ├── assets │ └── user1.jpg ├── windows │ ├── runner │ │ ├── resources │ │ │ └── app_icon.ico │ │ ├── resource.h │ │ ├── utils.h │ │ ├── runner.exe.manifest │ │ ├── flutter_window.h │ │ ├── main.cpp │ │ ├── CMakeLists.txt │ │ ├── utils.cpp │ │ ├── flutter_window.cpp │ │ ├── Runner.rc │ │ ├── win32_window.h │ │ └── win32_window.cpp │ ├── flutter │ │ ├── generated_plugin_registrant.cc │ │ ├── generated_plugin_registrant.h │ │ ├── generated_plugins.cmake │ │ └── CMakeLists.txt │ ├── .gitignore │ └── CMakeLists.txt ├── 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 │ │ │ │ ├── kotlin │ │ │ │ │ └── dev │ │ │ │ │ │ └── shiburagi │ │ │ │ │ │ └── drawerbehavior_example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── test │ └── widget_test.dart ├── README.md ├── lib │ ├── menus │ │ └── main.dart │ ├── pages │ │ ├── drawer_scale_icon.dart │ │ ├── drawer_scale_no_animation.dart │ │ ├── drawer_slide.dart │ │ ├── drawer_slide_menu_slide.dart │ │ ├── drawer_scale_right.dart │ │ ├── drawer_scale.dart │ │ ├── drawer_3d.dart │ │ ├── drawer_scale_gradient.dart │ │ ├── drawer_scale_left_right_inverse.dart │ │ ├── drawer_scale_left_3d_right_slide_.dart │ │ ├── drawer_scale_peek_left.dart │ │ ├── drawer_scale_left_right.dart │ │ ├── drawer_scale_peek_right.dart │ │ ├── drawer_with_child.dart │ │ ├── drawer_slide_with_footer.dart │ │ ├── drawer_slide_with_header.dart │ │ ├── drawer_custom_item_by_count.dart │ │ ├── drawer_slide_custom_appbar.dart │ │ └── drawer_custom_item.dart │ └── main.dart ├── .metadata ├── .gitignore └── pubspec.yaml ├── .vscode ├── settings.json └── launch.json ├── test └── drawerbehavior_test.dart ├── settings.json ├── lib ├── drawerbehavior.dart └── src │ ├── utils.dart │ ├── menu_item.dart │ ├── menu_list.dart │ └── builder.dart ├── .gitignore ├── .metadata ├── .github └── workflows │ ├── dart.yml │ └── publisher.yml ├── drawerbehavior.iml ├── LICENSE ├── .all-contributorsrc ├── analysis_options.yaml ├── pubspec.yaml ├── CHANGELOG.md └── README.md /.fvmrc: -------------------------------------------------------------------------------- 1 | { 2 | "flutter": "3.27.4" 3 | } -------------------------------------------------------------------------------- /example/web/CNAME: -------------------------------------------------------------------------------- 1 | drawerbehavior.zariman.dev -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dart.flutterSdkPath": ".fvm/versions/3.27.4" 3 | } -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/assets/user1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/assets/user1.jpg -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /test/drawerbehavior_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_test/flutter_test.dart'; 2 | 3 | void main() { 4 | test('adds one to input values', () {}); 5 | } 6 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { // In your settings.json 2 | "markdown.extension.toc.omittedFromToc": { 3 | // Use a path relative to your workspace. 4 | "README.md": [ 5 | "###" 6 | ] 7 | } 8 | } -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shiburagi/Drawer-Behavior-Flutter/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/shiburagi/Drawer-Behavior-Flutter/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/dev/shiburagi/drawerbehavior_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.shiburagi.drawerbehavior_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /lib/drawerbehavior.dart: -------------------------------------------------------------------------------- 1 | export 'package:drawerbehavior/src/menu_item.dart'; 2 | export 'package:drawerbehavior/src/side_drawer.dart'; 3 | export 'package:drawerbehavior/src/drawer_scaffold.dart'; 4 | export 'package:drawerbehavior/src/builder.dart'; 5 | -------------------------------------------------------------------------------- /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-8.3-all.zip 6 | -------------------------------------------------------------------------------- /example/windows/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 RegisterPlugins(flutter::PluginRegistry* registry) { 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | pubspec.lock 7 | 8 | build/ 9 | 10 | \.idea/ 11 | 12 | example/ios/Runner\.xcworkspace/xcshareddata/WorkspaceSettings\.xcsettings 13 | example/analysis_options.yaml 14 | 15 | # FVM Version Cache 16 | .fvm/ -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /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/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/macos/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 | -------------------------------------------------------------------------------- /lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | class Utils { 4 | static double fixed(double value, int decimal) { 5 | int fac = pow(10, decimal) as int; 6 | return (value * fac).round() / fac; 7 | } 8 | } 9 | 10 | extension ListExt on List { 11 | T? getOrNull(int index) => index < length ? this[index] : null; 12 | } 13 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/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: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: beta 9 | 10 | project_type: plugin 11 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import FlutterMacOS 2 | import Cocoa 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/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/windows/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 RegisterPlugins(flutter::PluginRegistry* 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 | -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 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/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.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": "Dart", 9 | "type": "dart", 10 | "request": "launch", 11 | "program": "example/lib/main.dart" 12 | } 13 | 14 | ] 15 | } -------------------------------------------------------------------------------- /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/windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /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/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('Verify Platform version', (WidgetTester tester) async { 12 | // Build our app and trigger a frame. 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # drawerbehavior_example 2 | 3 | Demonstrates how to use the drawerbehavior plugin. 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.io/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.io/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "minimal-ui", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /example/lib/menus/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | List> items = [ 5 | MenuItem( 6 | id: 0, 7 | title: 'THE PADDOCK', 8 | prefix: Icon(Icons.fastfood), 9 | ), 10 | MenuItem( 11 | id: 1, 12 | title: 'THE HERO', 13 | prefix: Icon(Icons.person), 14 | ), 15 | MenuItem( 16 | id: 2, 17 | title: 'HELP US GROW', 18 | prefix: Icon(Icons.terrain), 19 | ), 20 | MenuItem( 21 | id: 3, 22 | title: 'SETTINGS', 23 | prefix: Icon(Icons.settings), 24 | ), 25 | ]; 26 | final menu = Menu( 27 | items: items.map((e) => e.copyWith(prefix: null)).toList(), 28 | ); 29 | 30 | final menuWithIcon = Menu( 31 | items: items, 32 | ); 33 | -------------------------------------------------------------------------------- /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | name: Dart CI 2 | 3 | on: 4 | push: 5 | branches: [ master, Version-2.0.0 ] 6 | pull_request: 7 | branches: [ master, Version-2.0.0 ] 8 | 9 | jobs: 10 | test: 11 | name: Test on ${{ matrix.os }} 12 | runs-on: ${{ matrix.os }} 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest] 16 | steps: 17 | - uses: actions/checkout@v1 18 | - uses: actions/setup-java@v1 19 | with: 20 | java-version: '12.x' 21 | - uses: subosito/flutter-action@v1 22 | with: 23 | # flutter-version: '1.11.0' 24 | channel: 'beta' 25 | - run: dart --version 26 | - run: flutter --version 27 | - run: flutter pub get 28 | # - run: flutter test 29 | - run: | 30 | cd example 31 | flutter build apk 32 | -------------------------------------------------------------------------------- /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 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.1.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /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/windows/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}/windows 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}/windows plugins/${ffi_plugin}) 22 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 23 | endforeach(ffi_plugin) 24 | -------------------------------------------------------------------------------- /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 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /drawerbehavior.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Muhammad Norzariman Razari 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 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | example 18 | 19 | 20 | 21 | 24 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/publisher.yml: -------------------------------------------------------------------------------- 1 | # This workflow uses actions that are not certified by GitHub. 2 | # They are provided by a third-party and are governed by 3 | # separate terms of service, privacy policy, and support 4 | # documentation. 5 | 6 | name: Dart 7 | 8 | on: 9 | push: 10 | branches: [ "Version-*" ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | - name: Install Flutter 19 | uses: subosito/flutter-action@v2 20 | with: 21 | channel: stable # or: beta, master (or main) 22 | flutter-version: 3.27.4 23 | - name: Install dependencies 24 | run: flutter pub get 25 | # - name: Dart and Flutter Package Publisher 26 | # uses: k-paxian/dart-package-publisher@v1.6 27 | # with: 28 | # flutterBranch: stable 29 | # credentialJson: ${{ secrets.CREDENTIAL_JSON }} 30 | - name: Publish Dart/Flutter package 31 | # You may pin to the exact commit or the version. 32 | # uses: sakebook/actions-flutter-pub-publisher@ccd9fbba502ea7ef33ea2479e0cdac5a2a9766e1 33 | uses: afonsocraposo/actions-flutter-pub-publisher@v1.1.0 34 | with: 35 | credential: ${{ secrets.CREDENTIAL_JSON }} 36 | skip_test: true 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.Create(L"example", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/menu_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class Menu { 4 | final List> items; 5 | 6 | const Menu({ 7 | required this.items, 8 | }); 9 | } 10 | 11 | class MenuItem { 12 | final T? id; 13 | final String title; 14 | 15 | /// set icon from [MenuItem], if the icon is not null, the prefix must be null 16 | final IconData? icon; 17 | 18 | /// set prefix widget from [MenuItem], if the prefix is not null, the icon must be null 19 | final Widget? prefix; 20 | 21 | /// set prefix widget from [MenuItem] 22 | final Widget? suffix; 23 | 24 | /// set independent text style for title 25 | final TextStyle? textStyle; 26 | 27 | /// append data with [MenuItem], then can be use on itemBuilder 28 | final dynamic data; 29 | 30 | MenuItem({ 31 | this.id, 32 | required this.title, 33 | this.icon, 34 | this.prefix, 35 | this.suffix, 36 | this.textStyle, 37 | this.data, 38 | }) : assert(prefix == null || icon == null); 39 | 40 | MenuItem copyWith({ 41 | T? id, 42 | String? title, 43 | IconData? icon, 44 | Widget? prefix, 45 | Widget? suffix, 46 | TextStyle? textStyle, 47 | dynamic data, 48 | }) { 49 | return MenuItem( 50 | id: id ?? this.id, 51 | title: title ?? this.title, 52 | icon: icon, 53 | prefix: prefix, 54 | suffix: suffix, 55 | textStyle: textStyle ?? this.textStyle, 56 | data: data ?? this.data, 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "commitType": "docs", 8 | "commitConvention": "angular", 9 | "contributors": [ 10 | { 11 | "login": "trademunch", 12 | "name": "trademunch", 13 | "avatar_url": "https://avatars.githubusercontent.com/u/45367267?v=4", 14 | "profile": "https://github.com/trademunch", 15 | "contributions": [ 16 | "code" 17 | ] 18 | }, 19 | { 20 | "login": "anjarnaufals", 21 | "name": "anjarnaufals", 22 | "avatar_url": "https://avatars.githubusercontent.com/u/50995060?v=4", 23 | "profile": "https://github.com/anjarnaufals", 24 | "contributions": [ 25 | "code" 26 | ] 27 | }, 28 | { 29 | "login": "vladaman", 30 | "name": "Vladimir Vlach", 31 | "avatar_url": "https://avatars.githubusercontent.com/u/907206?v=4", 32 | "profile": "https://github.com/vladaman", 33 | "contributions": [ 34 | "code" 35 | ] 36 | }, 37 | { 38 | "login": "tenhaus", 39 | "name": "Chris Hayen", 40 | "avatar_url": "https://avatars.githubusercontent.com/u/1205495?v=4", 41 | "profile": "https://github.com/tenhaus", 42 | "contributions": [ 43 | "code" 44 | ] 45 | } 46 | ], 47 | "contributorsPerLine": 7, 48 | "skipCi": true, 49 | "repoType": "github", 50 | "repoHost": "https://github.com", 51 | "projectName": "Drawer-Behavior-Flutter", 52 | "projectOwner": "shiburagi" 53 | } 54 | -------------------------------------------------------------------------------- /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: "d8a9f9a52e5af486f80d932e838ee93861ffd863" 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: d8a9f9a52e5af486f80d932e838ee93861ffd863 17 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 18 | - platform: android 19 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 20 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 21 | - platform: ios 22 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 23 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 24 | - platform: web 25 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 26 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 27 | - platform: windows 28 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 29 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 30 | 31 | # User provided section 32 | 33 | # List of Local paths (relative to this file) that should be 34 | # ignored by the migrate tool. 35 | # 36 | # Files that are not part of the templates will be ignored by default. 37 | unmanaged_files: 38 | - 'lib/main.dart' 39 | - 'ios/Runner.xcodeproj/project.pbxproj' 40 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id "dev.flutter.flutter-gradle-plugin" 6 | } 7 | 8 | android { 9 | namespace = "dev.shiburagi.drawerbehavior_example" 10 | compileSdk = flutter.compileSdkVersion 11 | ndkVersion = flutter.ndkVersion 12 | 13 | compileOptions { 14 | sourceCompatibility = JavaVersion.VERSION_1_8 15 | targetCompatibility = JavaVersion.VERSION_1_8 16 | } 17 | 18 | kotlinOptions { 19 | jvmTarget = JavaVersion.VERSION_1_8 20 | } 21 | 22 | defaultConfig { 23 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 24 | applicationId = "dev.shiburagi.drawerbehavior_example" 25 | // You can update the following values to match your application needs. 26 | // For more information, see: https://flutter.dev/to/review-gradle-config. 27 | minSdk = flutter.minSdkVersion 28 | targetSdk = flutter.targetSdkVersion 29 | versionCode = flutter.versionCode 30 | versionName = flutter.versionName 31 | } 32 | 33 | buildTypes { 34 | release { 35 | // TODO: Add your own signing config for the release build. 36 | // Signing with the debug keys for now, so `flutter run --release` works. 37 | signingConfig = signingConfigs.debug 38 | } 39 | } 40 | } 41 | 42 | flutter { 43 | source = "../.." 44 | } 45 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | analyzer: 11 | errors: 12 | depend_on_referenced_packages: ignore 13 | include: package:flutter_lints/flutter.yaml 14 | 15 | linter: 16 | # The lint rules applied to this project can be customized in the 17 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 18 | # included above or to enable additional rules. A list of all available lints 19 | # and their documentation is published at https://dart.dev/lints. 20 | # 21 | # Instead of disabling a lint rule for the entire project in the 22 | # section below, it can also be suppressed for a single line of code 23 | # or a specific dart file by using the `// ignore: name_of_lint` and 24 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 25 | # producing the lint. 26 | rules: 27 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 28 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 29 | 30 | # Additional information about this file can be found at 31 | # https://dart.dev/guides/language/analysis-options 32 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_icon.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerScaleIcon extends StatefulWidget { 6 | const DrawerScaleIcon({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerScaleIconState(); 10 | } 11 | 12 | class _DrawerScaleIconState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menuWithIcon.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | appBar: AppBar( 25 | title: Text("Drawer - Scale with Icon"), 26 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 27 | drawers: [ 28 | SideDrawer( 29 | percentage: 0.6, 30 | menu: menuWithIcon, 31 | animation: true, 32 | color: Theme.of(context).primaryColor, 33 | selectedItemId: selectedMenuItemId, 34 | onMenuItemSelected: (itemId) { 35 | setState(() { 36 | selectedMenuItemId = itemId; 37 | }); 38 | }, 39 | ) 40 | ], 41 | builder: (context, id) => IndexedStack( 42 | index: id, 43 | children: menu.items 44 | .map((e) => Center( 45 | child: Text("Page~${e.title}"), 46 | )) 47 | .toList(), 48 | ), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_no_animation.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerScaleNoAnimation extends StatefulWidget { 6 | const DrawerScaleNoAnimation({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerScaleNoAnimationState(); 10 | } 11 | 12 | class _DrawerScaleNoAnimationState extends State { 13 | int? selectedMenuItemId; 14 | @override 15 | void initState() { 16 | selectedMenuItemId = menu.items[0].id; 17 | super.initState(); 18 | } 19 | 20 | @override 21 | Widget build(BuildContext context) { 22 | return DrawerScaffold( 23 | appBar: AppBar( 24 | title: Text("Drawer - Scale No Animaton"), 25 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 26 | drawers: [ 27 | SideDrawer( 28 | percentage: 0.6, 29 | menu: menu, 30 | animation: false, 31 | color: Theme.of(context).primaryColor, 32 | selectedItemId: selectedMenuItemId, 33 | onMenuItemSelected: (itemId) { 34 | setState(() { 35 | selectedMenuItemId = itemId; 36 | }); 37 | }, 38 | ) 39 | ], 40 | builder: (context, id) => IndexedStack( 41 | index: id, 42 | children: menu.items 43 | .map((e) => Center( 44 | child: Text("Page~${e.title}"), 45 | )) 46 | .toList(), 47 | ), 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_slide.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerSlide extends StatefulWidget { 6 | const DrawerSlide({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerSlideState(); 10 | } 11 | 12 | class _DrawerSlideState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | appBar: AppBar( 25 | title: Text("Drawer - Slide"), 26 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 27 | drawers: [ 28 | SideDrawer( 29 | percentage: 1, 30 | textStyle: TextStyle(color: Colors.white, fontSize: 24.0), 31 | menu: menu, 32 | animation: false, 33 | alignment: Alignment.topLeft, 34 | color: Theme.of(context).primaryColor, 35 | selectedItemId: selectedMenuItemId, 36 | onMenuItemSelected: (itemId) { 37 | setState(() { 38 | selectedMenuItemId = itemId; 39 | }); 40 | }, 41 | ) 42 | ], 43 | builder: (context, id) => IndexedStack( 44 | index: id, 45 | children: menu.items 46 | .map((e) => Center( 47 | child: Text("Page~${e.title}"), 48 | )) 49 | .toList(), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /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/lib/pages/drawer_slide_menu_slide.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerSlideMenuSlide extends StatefulWidget { 6 | const DrawerSlideMenuSlide({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerSlideMenuSlideState(); 10 | } 11 | 12 | class _DrawerSlideMenuSlideState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | appBar: AppBar( 25 | title: Text("Drawer and Menu - Slide"), 26 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 27 | drawers: [ 28 | SideDrawer( 29 | percentage: 1, 30 | slide: true, 31 | textStyle: TextStyle(color: Colors.white, fontSize: 24.0), 32 | menu: menu, 33 | animation: false, 34 | alignment: Alignment.topLeft, 35 | color: Theme.of(context).primaryColor, 36 | selectedItemId: selectedMenuItemId, 37 | onMenuItemSelected: (itemId) { 38 | setState(() { 39 | selectedMenuItemId = itemId; 40 | }); 41 | }, 42 | ) 43 | ], 44 | builder: (context, id) => IndexedStack( 45 | index: id, 46 | children: menu.items 47 | .map((e) => Center( 48 | child: Text("Page~${e.title}"), 49 | )) 50 | .toList(), 51 | ), 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_right.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerRight extends StatefulWidget { 6 | const DrawerRight({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerRightState(); 10 | } 11 | 12 | class _DrawerRightState extends State { 13 | int? selectedMenuItemId; 14 | DrawerScaffoldController controller = DrawerScaffoldController(); 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | controller: controller, 25 | appBar: AppBar(title: Text("Drawer - Right"), actions: [ 26 | IconButton( 27 | icon: Icon(Icons.notifications_none), 28 | onPressed: () { 29 | controller.toggle(Direction.right); 30 | }) 31 | ]), 32 | drawers: [ 33 | SideDrawer( 34 | percentage: 0.6, 35 | menu: menu, 36 | direction: Direction.right, 37 | animation: true, 38 | color: Theme.of(context).primaryColor, 39 | selectedItemId: selectedMenuItemId, 40 | onMenuItemSelected: (itemId) { 41 | setState(() { 42 | selectedMenuItemId = itemId; 43 | }); 44 | }, 45 | ), 46 | ], 47 | builder: (context, id) => IndexedStack( 48 | index: id, 49 | children: menu.items 50 | .map((e) => Center( 51 | child: Text("Page~${e.title}"), 52 | )) 53 | .toList(), 54 | ), 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | $(DEVELOPMENT_LANGUAGE) 9 | CFBundleDisplayName 10 | Example 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | example 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(FLUTTER_BUILD_NAME) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | UIApplicationSupportsIndirectInputEvents 30 | 31 | UILaunchStoryboardName 32 | LaunchScreen 33 | UIMainStoryboardFile 34 | Main 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Add preprocessor definitions for the build version. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") 25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") 26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") 27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") 28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") 29 | 30 | # Disable Windows macros that collide with C++ standard library functions. 31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 32 | 33 | # Add dependency libraries and include directories. Add any application-specific 34 | # dependencies here. 35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") 37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 38 | 39 | # Run the Flutter tool portions of the build. This must not be removed. 40 | add_dependencies(${BINARY_NAME} flutter_assemble) 41 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerScale extends StatefulWidget { 6 | const DrawerScale({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerScaleState(); 10 | } 11 | 12 | class _DrawerScaleState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | appBar: AppBar( 25 | title: Text("Drawer - Scale"), 26 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 27 | onSlide: (drawer, value) { 28 | debugPrint("[LOG] Drawer ${drawer.direction} $value"); 29 | }, 30 | onOpened: (drawer) { 31 | debugPrint("[LOG] Drawer ${drawer.direction} opened"); 32 | }, 33 | onClosed: (drawer) { 34 | debugPrint("[LOG] Drawer ${drawer.direction} closed"); 35 | }, 36 | drawers: [ 37 | SideDrawer( 38 | percentage: 0.6, 39 | menu: menu, 40 | direction: Direction.left, 41 | animation: true, 42 | // alignment: Alignment.topLeft, 43 | color: Theme.of(context).primaryColor, 44 | selectedItemId: selectedMenuItemId, 45 | onMenuItemSelected: (itemId) { 46 | setState(() { 47 | selectedMenuItemId = itemId; 48 | }); 49 | }, 50 | ) 51 | ], 52 | builder: (context, id) => IndexedStack( 53 | index: id, 54 | children: menu.items 55 | .map((e) => Center( 56 | child: Text("Page~${e.title}"), 57 | )) 58 | .toList(), 59 | ), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_3d.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class Drawer3d extends StatefulWidget { 6 | const Drawer3d({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _Drawer3dState(); 10 | } 11 | 12 | class _Drawer3dState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | appBar: AppBar( 25 | title: Text("Drawer - 3D"), 26 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 27 | drawers: [ 28 | SideDrawer( 29 | percentage: 0.8, 30 | degree: 45, 31 | menu: menu, 32 | direction: Direction.left, 33 | animation: true, 34 | color: Theme.of(context).primaryColor, 35 | selectedItemId: selectedMenuItemId, 36 | onMenuItemSelected: (itemId) { 37 | setState(() { 38 | selectedMenuItemId = itemId; 39 | }); 40 | }, 41 | ), 42 | SideDrawer( 43 | degree: 45, 44 | menu: menu, 45 | direction: Direction.right, 46 | animation: true, 47 | color: Theme.of(context).primaryColor, 48 | selectedItemId: selectedMenuItemId, 49 | onMenuItemSelected: (itemId) { 50 | setState(() { 51 | selectedMenuItemId = itemId; 52 | }); 53 | }, 54 | ), 55 | ], 56 | builder: (context, id) => IndexedStack( 57 | index: id, 58 | children: menu.items 59 | .map((e) => Center( 60 | child: Text("Page~${e.title}"), 61 | )) 62 | .toList(), 63 | ), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /example/windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr) 51 | -1; // remove the trailing null character 52 | int input_length = (int)wcslen(utf16_string); 53 | std::string utf8_string; 54 | if (target_length <= 0 || target_length > utf8_string.max_size()) { 55 | return utf8_string; 56 | } 57 | utf8_string.resize(target_length); 58 | int converted_length = ::WideCharToMultiByte( 59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 60 | input_length, utf8_string.data(), target_length, nullptr, nullptr); 61 | if (converted_length == 0) { 62 | return std::string(); 63 | } 64 | return utf8_string; 65 | } 66 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: drawerbehavior_example 2 | description: Demonstrates how to use the drawerbehavior plugin. 3 | publish_to: "none" 4 | 5 | environment: 6 | sdk: '>=2.12.0 <4.0.0' 7 | 8 | dependencies: 9 | flutter: 10 | sdk: flutter 11 | 12 | # The following adds the Cupertino Icons font to your application. 13 | # Use with the CupertinoIcons class for iOS style icons. 14 | cupertino_icons: ^1.0.6 15 | 16 | dev_dependencies: 17 | flutter_test: 18 | sdk: flutter 19 | 20 | drawerbehavior: 21 | path: ../ 22 | flutter_lints: ^5.0.0 23 | 24 | # For information on the generic Dart part of this file, see the 25 | # following page: https://www.dartlang.org/tools/pub/pubspec 26 | 27 | # The following section is specific to Flutter. 28 | flutter: 29 | # The following line ensures that the Material Icons font is 30 | # included with your application, so that you can use the icons in 31 | # the material Icons class. 32 | uses-material-design: true 33 | 34 | assets: 35 | - assets/ 36 | # To add assets to your application, add an assets section, like this: 37 | # assets: 38 | # - images/a_dot_burr.jpeg 39 | # - images/a_dot_ham.jpeg 40 | 41 | # An image asset can refer to one or more resolution-specific "variants", see 42 | # https://flutter.io/assets-and-images/#resolution-aware. 43 | 44 | # For details regarding adding assets from package dependencies, see 45 | # https://flutter.io/assets-and-images/#from-packages 46 | 47 | # To add custom fonts to your application, add a fonts section here, 48 | # in this "flutter" section. Each entry in this list should have a 49 | # "family" key with the font family name, and a "fonts" key with a 50 | # list giving the asset and other descriptors for the font. For 51 | # example: 52 | # fonts: 53 | # - family: Schyler 54 | # fonts: 55 | # - asset: fonts/Schyler-Regular.ttf 56 | # - asset: fonts/Schyler-Italic.ttf 57 | # style: italic 58 | # - family: Trajan Pro 59 | # fonts: 60 | # - asset: fonts/TrajanPro.ttf 61 | # - asset: fonts/TrajanPro_Bold.ttf 62 | # weight: 700 63 | # 64 | # For details regarding fonts from package dependencies, 65 | # see https://flutter.io/custom-fonts/#from-packages 66 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_gradient.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerScaleGradient extends StatefulWidget { 6 | const DrawerScaleGradient({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerScaleGradientState(); 10 | } 11 | 12 | class _DrawerScaleGradientState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Container( 24 | decoration: BoxDecoration( 25 | gradient: LinearGradient( 26 | colors: [Colors.blue, Colors.green], 27 | begin: Alignment.topLeft, 28 | end: Alignment.bottomRight, 29 | ), 30 | ), 31 | child: DrawerScaffold( 32 | backgroundColor: Colors.transparent, 33 | appBar: AppBar( 34 | title: Text("Drawer - Scale"), 35 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 36 | onSlide: (drawer, value) { 37 | debugPrint("[LOG] Drawer ${drawer.direction} $value"); 38 | }, 39 | onOpened: (drawer) { 40 | debugPrint("[LOG] Drawer ${drawer.direction} opened"); 41 | }, 42 | onClosed: (drawer) { 43 | debugPrint("[LOG] Drawer ${drawer.direction} closed"); 44 | }, 45 | drawers: [ 46 | SideDrawer( 47 | percentage: 0.6, 48 | menu: menu, 49 | direction: Direction.left, 50 | animation: true, 51 | color: Colors.transparent, 52 | selectedItemId: selectedMenuItemId, 53 | onMenuItemSelected: (itemId) { 54 | setState(() { 55 | selectedMenuItemId = itemId; 56 | }); 57 | }, 58 | ) 59 | ], 60 | builder: (context, id) => IndexedStack( 61 | index: id, 62 | children: menu.items 63 | .map((e) => Center( 64 | child: Text("Page~${e.title}"), 65 | )) 66 | .toList(), 67 | ), 68 | ), 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_left_right_inverse.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerLeftAndRightInverse extends StatefulWidget { 6 | const DrawerLeftAndRightInverse({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => 10 | _DrawerLeftAndRightInverseState(); 11 | } 12 | 13 | class _DrawerLeftAndRightInverseState extends State { 14 | int? selectedMenuItemId; 15 | DrawerScaffoldController controller = DrawerScaffoldController(); 16 | @override 17 | void initState() { 18 | selectedMenuItemId = menu.items[0].id; 19 | super.initState(); 20 | } 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return DrawerScaffold( 25 | controller: controller, 26 | appBar: AppBar(title: Text("Drawer - Left & Right"), actions: [ 27 | IconButton( 28 | icon: Icon(Icons.notifications_none), 29 | onPressed: () { 30 | controller.toggle(Direction.left); 31 | }) 32 | ]), 33 | defaultDirection: Direction.right, 34 | drawers: [ 35 | SideDrawer( 36 | percentage: 0.6, 37 | menu: menu, 38 | direction: Direction.left, 39 | animation: true, 40 | color: Theme.of(context).primaryColor, 41 | selectedItemId: selectedMenuItemId, 42 | onMenuItemSelected: (itemId) { 43 | setState(() { 44 | selectedMenuItemId = itemId; 45 | }); 46 | }, 47 | ), 48 | SideDrawer( 49 | menu: menu, 50 | direction: Direction.right, 51 | animation: true, 52 | selectorColor: Colors.white, 53 | color: Theme.of(context).colorScheme.secondary, 54 | selectedItemId: selectedMenuItemId, 55 | onMenuItemSelected: (itemId) { 56 | setState(() { 57 | selectedMenuItemId = itemId; 58 | }); 59 | }, 60 | ), 61 | ], 62 | builder: (context, id) => IndexedStack( 63 | index: id, 64 | children: menu.items 65 | .map((e) => Center( 66 | child: Text("Page~${e.title}"), 67 | )) 68 | .toList(), 69 | ), 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: drawerbehavior 2 | description: Drawer behavior is a library that provide an extra behavior on drawer, such as, move view or scaling view's height while drawer on slide.. 3 | version: 3.0.4 4 | homepage: https://github.com/shiburagi/Drawer-Behavior-Flutter 5 | repository: https://github.com/shiburagi/Drawer-Behavior-Flutter 6 | 7 | environment: 8 | sdk: ">=2.12.0 <4.0.0" 9 | flutter: ">=3.22.0" 10 | 11 | dependencies: 12 | flutter: 13 | sdk: flutter 14 | 15 | dev_dependencies: 16 | flutter_lints: ^5.0.0 17 | flutter_test: 18 | sdk: flutter 19 | pedantic: ^1.10.0 20 | # For information on the generic Dart part of this file, see the 21 | # following page: https://www.dartlang.org/tools/pub/pubspec 22 | 23 | # The following section is specific to Flutter. 24 | # flutter: 25 | # This section identifies this Flutter project as a plugin project. 26 | # The androidPackage and pluginClass identifiers should not ordinarily 27 | # be modified. They are used by the tooling to maintain consistency when 28 | # adding or updating assets for this project. 29 | # module: 30 | # androidX: true 31 | # webPackage: drawerbehavior 32 | # androidPackage: com.infideap.drawerbehavior 33 | # iosBundleIdentifier: com.infideap.drawerbehavior 34 | 35 | # To add assets to your plugin package, add an assets section, like this: 36 | # assets: 37 | # - images/a_dot_burr.jpeg 38 | # - images/a_dot_ham.jpeg 39 | # 40 | # For details regarding assets in packages, see 41 | # https://flutter.io/assets-and-images/#from-packages 42 | # 43 | # An image asset can refer to one or more resolution-specific "variants", see 44 | # https://flutter.io/assets-and-images/#resolution-aware. 45 | 46 | # To add custom fonts to your plugin package, add a fonts section here, 47 | # in this "flutter" section. Each entry in this list should have a 48 | # "family" key with the font family name, and a "fonts" key with a 49 | # list giving the asset and other descriptors for the font. For 50 | # example: 51 | # fonts: 52 | # - family: Schyler 53 | # fonts: 54 | # - asset: fonts/Schyler-Regular.ttf 55 | # - asset: fonts/Schyler-Italic.ttf 56 | # style: italic 57 | # - family: Trajan Pro 58 | # fonts: 59 | # - asset: fonts/TrajanPro.ttf 60 | # - asset: fonts/TrajanPro_Bold.ttf 61 | # weight: 700 62 | # 63 | # For details regarding fonts in packages, see 64 | # https://flutter.io/custom-fonts/#from-packages 65 | -------------------------------------------------------------------------------- /example/windows/runner/flutter_window.cpp: -------------------------------------------------------------------------------- 1 | #include "flutter_window.h" 2 | 3 | #include 4 | 5 | #include "flutter/generated_plugin_registrant.h" 6 | 7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project) 8 | : project_(project) {} 9 | 10 | FlutterWindow::~FlutterWindow() {} 11 | 12 | bool FlutterWindow::OnCreate() { 13 | if (!Win32Window::OnCreate()) { 14 | return false; 15 | } 16 | 17 | RECT frame = GetClientArea(); 18 | 19 | // The size here must match the window dimensions to avoid unnecessary surface 20 | // creation / destruction in the startup path. 21 | flutter_controller_ = std::make_unique( 22 | frame.right - frame.left, frame.bottom - frame.top, project_); 23 | // Ensure that basic setup of the controller was successful. 24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) { 25 | return false; 26 | } 27 | RegisterPlugins(flutter_controller_->engine()); 28 | SetChildContent(flutter_controller_->view()->GetNativeWindow()); 29 | 30 | flutter_controller_->engine()->SetNextFrameCallback([&]() { 31 | this->Show(); 32 | }); 33 | 34 | // Flutter can complete the first frame before the "show window" callback is 35 | // registered. The following call ensures a frame is pending to ensure the 36 | // window is shown. It is a no-op if the first frame hasn't completed yet. 37 | flutter_controller_->ForceRedraw(); 38 | 39 | return true; 40 | } 41 | 42 | void FlutterWindow::OnDestroy() { 43 | if (flutter_controller_) { 44 | flutter_controller_ = nullptr; 45 | } 46 | 47 | Win32Window::OnDestroy(); 48 | } 49 | 50 | LRESULT 51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 52 | WPARAM const wparam, 53 | LPARAM const lparam) noexcept { 54 | // Give Flutter, including plugins, an opportunity to handle window messages. 55 | if (flutter_controller_) { 56 | std::optional result = 57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 58 | lparam); 59 | if (result) { 60 | return *result; 61 | } 62 | } 63 | 64 | switch (message) { 65 | case WM_FONTCHANGE: 66 | flutter_controller_->engine()->ReloadSystemFonts(); 67 | break; 68 | } 69 | 70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 71 | } 72 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_left_3d_right_slide_.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerLeft3DAndRightSlide extends StatefulWidget { 6 | const DrawerLeft3DAndRightSlide({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => 10 | _DrawerLeft3DAndRightSlideState(); 11 | } 12 | 13 | class _DrawerLeft3DAndRightSlideState extends State { 14 | int? selectedMenuItemId; 15 | DrawerScaffoldController controller = DrawerScaffoldController(); 16 | @override 17 | void initState() { 18 | selectedMenuItemId = menu.items[0].id; 19 | super.initState(); 20 | } 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return DrawerScaffold( 25 | controller: controller, 26 | appBar: AppBar(title: Text("Drawer - Left(3D) & Right(Slide)"), actions: [ 27 | IconButton( 28 | icon: Icon(Icons.notifications_none), 29 | onPressed: () { 30 | controller.toggle(Direction.right); 31 | }) 32 | ]), 33 | drawers: [ 34 | SideDrawer( 35 | percentage: 0.6, 36 | degree: 45, 37 | menu: menu, 38 | direction: Direction.left, 39 | animation: true, 40 | color: Theme.of(context).primaryColor, 41 | selectedItemId: selectedMenuItemId, 42 | onMenuItemSelected: (itemId) { 43 | setState(() { 44 | selectedMenuItemId = itemId; 45 | }); 46 | }, 47 | ), 48 | SideDrawer( 49 | cornerRadius: 0, 50 | menu: menu, 51 | percentage: 1.0, 52 | direction: Direction.right, 53 | animation: true, 54 | selectorColor: Colors.white, 55 | color: Theme.of(context).colorScheme.secondary, 56 | selectedItemId: selectedMenuItemId, 57 | onMenuItemSelected: (itemId) { 58 | setState(() { 59 | selectedMenuItemId = itemId; 60 | }); 61 | }, 62 | ), 63 | ], 64 | builder: (context, id) => IndexedStack( 65 | index: id, 66 | children: menu.items 67 | .map((e) => Center( 68 | child: Text("Page~${e.title}"), 69 | )) 70 | .toList(), 71 | ), 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/src/menu_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class MenuListItem extends StatelessWidget { 5 | final String title; 6 | final bool? isSelected; 7 | final bool drawBorder; 8 | final Color? selectorColor; 9 | final TextStyle? textStyle; 10 | final SideDrawer? menuView; 11 | final Widget? icon; 12 | final Widget? suffix; 13 | final Direction direction; 14 | final double? width; 15 | final EdgeInsets? padding; 16 | 17 | const MenuListItem({ 18 | Key? key, 19 | required this.title, 20 | this.isSelected, 21 | this.menuView, 22 | required this.textStyle, 23 | required this.selectorColor, 24 | this.icon, 25 | this.drawBorder = false, 26 | this.direction = Direction.right, 27 | this.width, 28 | this.padding, 29 | this.suffix, 30 | }) : super(key: key); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | TextStyle textStyle = this 35 | .textStyle! 36 | .copyWith(color: isSelected! ? selectorColor : this.textStyle!.color); 37 | 38 | List children = []; 39 | if (icon != null) { 40 | children.add(Padding( 41 | padding: EdgeInsets.only(right: 16), 42 | child: IconTheme( 43 | data: IconThemeData(color: textStyle.color), child: icon!), 44 | )); 45 | } 46 | children.add( 47 | Expanded( 48 | flex: 1, 49 | child: Text( 50 | title, 51 | style: textStyle, 52 | ), 53 | ), 54 | ); 55 | if (suffix != null) { 56 | children.add(Padding( 57 | padding: EdgeInsets.only(right: 12), 58 | child: IconTheme( 59 | data: IconThemeData(color: textStyle.color), child: suffix!), 60 | )); 61 | } 62 | return Stack( 63 | children: [ 64 | if (drawBorder) 65 | Positioned( 66 | top: 0, 67 | bottom: 0, 68 | child: Container( 69 | width: 4, 70 | color: isSelected == true ? selectorColor! : Colors.transparent, 71 | ), 72 | ), 73 | Container( 74 | width: width, 75 | alignment: Alignment.centerRight, 76 | child: Padding( 77 | padding: menuView?.padding ?? EdgeInsets.zero, 78 | child: Row( 79 | mainAxisAlignment: MainAxisAlignment.start, 80 | children: children, 81 | ), 82 | ), 83 | ), 84 | ], 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_peek_left.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerPeekLeft extends StatefulWidget { 6 | const DrawerPeekLeft({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerPeekLeftState(); 10 | } 11 | 12 | class _DrawerPeekLeftState extends State { 13 | int? selectedMenuItemId; 14 | DrawerScaffoldController controller = DrawerScaffoldController(); 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | controller: controller, 25 | appBar: AppBar(title: Text("Drawer - Peek Left"), actions: [ 26 | IconButton( 27 | icon: Icon(Icons.notifications_none), 28 | onPressed: () { 29 | controller.toggle(Direction.right); 30 | }) 31 | ]), 32 | onSlide: (drawer, value) { 33 | debugPrint("[LOG] Drawer ${drawer.direction} $value"); 34 | }, 35 | onOpened: (drawer) { 36 | debugPrint("[LOG] Drawer ${drawer.direction} opened"); 37 | }, 38 | onClosed: (drawer) { 39 | debugPrint("[LOG] Drawer ${drawer.direction} closed"); 40 | }, 41 | drawers: [ 42 | SideDrawer( 43 | peekMenu: true, 44 | percentage: 1, 45 | menu: menuWithIcon, 46 | direction: Direction.left, 47 | animation: true, 48 | color: Theme.of(context).primaryColor, 49 | selectedItemId: selectedMenuItemId, 50 | onMenuItemSelected: (itemId) { 51 | setState(() { 52 | selectedMenuItemId = itemId; 53 | }); 54 | }, 55 | ), 56 | SideDrawer( 57 | menu: menu, 58 | direction: Direction.right, 59 | animation: true, 60 | selectorColor: Colors.white, 61 | color: Theme.of(context).colorScheme.secondary, 62 | selectedItemId: selectedMenuItemId, 63 | onMenuItemSelected: (itemId) { 64 | setState(() { 65 | selectedMenuItemId = itemId; 66 | }); 67 | }, 68 | ), 69 | ], 70 | builder: (context, id) => IndexedStack( 71 | index: id, 72 | children: menu.items 73 | .map((e) => Center( 74 | child: Text("Page~${e.title}"), 75 | )) 76 | .toList(), 77 | ), 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_left_right.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerLeftAndRight extends StatefulWidget { 6 | const DrawerLeftAndRight({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerLeftAndRightState(); 10 | } 11 | 12 | class _DrawerLeftAndRightState extends State { 13 | int? selectedMenuItemId; 14 | DrawerScaffoldController controller = DrawerScaffoldController(); 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | controller: controller, 25 | appBar: AppBar(title: Text("Drawer - Left & Right"), actions: [ 26 | IconButton( 27 | icon: Icon(Icons.notifications_none), 28 | onPressed: () { 29 | controller.toggle(Direction.right); 30 | }) 31 | ]), 32 | onSlide: (drawer, value) { 33 | debugPrint("[LOG] Drawer ${drawer.direction} $value"); 34 | }, 35 | onOpened: (drawer) { 36 | debugPrint("[LOG] Drawer ${drawer.direction} opened"); 37 | }, 38 | onClosed: (drawer) { 39 | debugPrint("[LOG] Drawer ${drawer.direction} closed"); 40 | }, 41 | drawers: [ 42 | SideDrawer( 43 | percentage: 0.6, 44 | menu: menu, 45 | direction: Direction.left, 46 | animation: true, 47 | color: Theme.of(context).primaryColor, 48 | selectedItemId: selectedMenuItemId, 49 | onMenuItemSelected: (itemId) { 50 | setState(() { 51 | selectedMenuItemId = itemId; 52 | }); 53 | }, 54 | ), 55 | SideDrawer( 56 | menu: menu, 57 | percentage: 0.7, 58 | // elevation: 0, 59 | direction: Direction.right, 60 | animation: true, 61 | selectorColor: Colors.white, 62 | color: Theme.of(context).colorScheme.secondary, 63 | selectedItemId: selectedMenuItemId, 64 | onMenuItemSelected: (itemId) { 65 | setState(() { 66 | selectedMenuItemId = itemId; 67 | }); 68 | }, 69 | ), 70 | ], 71 | builder: (context, id) => IndexedStack( 72 | index: id, 73 | children: menu.items 74 | .map((e) => Center( 75 | child: Text("Page~${e.title}"), 76 | )) 77 | .toList(), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_scale_peek_right.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerPeekRight extends StatefulWidget { 6 | const DrawerPeekRight({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerPeekRightState(); 10 | } 11 | 12 | class _DrawerPeekRightState extends State { 13 | int? selectedMenuItemId; 14 | DrawerScaffoldController controller = DrawerScaffoldController(); 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return DrawerScaffold( 24 | controller: controller, 25 | defaultDirection: Direction.right, 26 | appBar: AppBar(title: Text("Drawer - Peek Right"), actions: [ 27 | IconButton( 28 | icon: Icon(Icons.notifications_none), 29 | onPressed: () { 30 | controller.toggle(Direction.left); 31 | }) 32 | ]), 33 | onSlide: (drawer, value) { 34 | debugPrint("[LOG] Drawer ${drawer.direction} $value"); 35 | }, 36 | onOpened: (drawer) { 37 | debugPrint("[LOG] Drawer ${drawer.direction} opened"); 38 | }, 39 | onClosed: (drawer) { 40 | debugPrint("[LOG] Drawer ${drawer.direction} closed"); 41 | }, 42 | drawers: [ 43 | SideDrawer( 44 | peekMenu: true, 45 | percentage: 1, 46 | menu: menuWithIcon, 47 | direction: Direction.right, 48 | animation: true, 49 | color: Theme.of(context).primaryColor, 50 | selectedItemId: selectedMenuItemId, 51 | onMenuItemSelected: (itemId) { 52 | setState(() { 53 | selectedMenuItemId = itemId; 54 | }); 55 | }, 56 | ), 57 | SideDrawer( 58 | menu: menu, 59 | direction: Direction.left, 60 | animation: true, 61 | selectorColor: Colors.white, 62 | color: Theme.of(context).colorScheme.secondary, 63 | selectedItemId: selectedMenuItemId, 64 | onMenuItemSelected: (itemId) { 65 | setState(() { 66 | selectedMenuItemId = itemId; 67 | }); 68 | }, 69 | ), 70 | ], 71 | builder: (context, id) => IndexedStack( 72 | index: id, 73 | children: menu.items 74 | .map((e) => Center( 75 | child: Text("Page~${e.title}"), 76 | )) 77 | .toList(), 78 | ), 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.10) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | 12 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 13 | # which isn't available in 3.10. 14 | function(list_prepend LIST_NAME PREFIX) 15 | set(NEW_LIST "") 16 | foreach(element ${${LIST_NAME}}) 17 | list(APPEND NEW_LIST "${PREFIX}${element}") 18 | endforeach(element) 19 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 20 | endfunction() 21 | 22 | # === Flutter Library === 23 | # System-level dependencies. 24 | find_package(PkgConfig REQUIRED) 25 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 26 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 27 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 28 | 29 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 30 | 31 | # Published to parent scope for install step. 32 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 33 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 34 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 35 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 36 | 37 | list(APPEND FLUTTER_LIBRARY_HEADERS 38 | "fl_basic_message_channel.h" 39 | "fl_binary_codec.h" 40 | "fl_binary_messenger.h" 41 | "fl_dart_project.h" 42 | "fl_engine.h" 43 | "fl_json_message_codec.h" 44 | "fl_json_method_codec.h" 45 | "fl_message_codec.h" 46 | "fl_method_call.h" 47 | "fl_method_channel.h" 48 | "fl_method_codec.h" 49 | "fl_method_response.h" 50 | "fl_plugin_registrar.h" 51 | "fl_plugin_registry.h" 52 | "fl_standard_message_codec.h" 53 | "fl_standard_method_codec.h" 54 | "fl_string_codec.h" 55 | "fl_value.h" 56 | "fl_view.h" 57 | "flutter_linux.h" 58 | ) 59 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 60 | add_library(flutter INTERFACE) 61 | target_include_directories(flutter INTERFACE 62 | "${EPHEMERAL_DIR}" 63 | ) 64 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 65 | target_link_libraries(flutter INTERFACE 66 | PkgConfig::GTK 67 | PkgConfig::GLIB 68 | PkgConfig::GIO 69 | ) 70 | add_dependencies(flutter flutter_assemble) 71 | 72 | # === Flutter tool backend === 73 | # _phony_ is a non-existent file to force this command to run every time, 74 | # since currently there's no way to get a full input/output list from the 75 | # flutter tool. 76 | add_custom_command( 77 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 78 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 79 | COMMAND ${CMAKE_COMMAND} -E env 80 | ${FLUTTER_TOOL_ENVIRONMENT} 81 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 82 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 83 | VERBATIM 84 | ) 85 | add_custom_target(flutter_assemble DEPENDS 86 | "${FLUTTER_LIBRARY}" 87 | ${FLUTTER_LIBRARY_HEADERS} 88 | ) 89 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_with_child.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerWithChild extends StatefulWidget { 6 | const DrawerWithChild({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerWithChildState(); 10 | } 11 | 12 | class _DrawerWithChildState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | Widget headerView(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Container( 25 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 26 | child: Row( 27 | children: [ 28 | Container( 29 | width: 48.0, 30 | height: 48.0, 31 | decoration: BoxDecoration( 32 | shape: BoxShape.circle, 33 | image: DecorationImage( 34 | fit: BoxFit.fill, 35 | image: AssetImage("assets/user1.jpg")))), 36 | Container( 37 | margin: EdgeInsets.only(left: 16), 38 | child: Column( 39 | mainAxisAlignment: MainAxisAlignment.start, 40 | crossAxisAlignment: CrossAxisAlignment.start, 41 | children: [ 42 | Text( 43 | "John Witch", 44 | style: Theme.of(context) 45 | .textTheme 46 | .titleMedium 47 | ?.copyWith(color: Colors.white), 48 | ), 49 | Text( 50 | "test123@gmail.com", 51 | style: Theme.of(context) 52 | .textTheme 53 | .titleSmall 54 | ?.copyWith(color: Colors.white.withAlpha(200)), 55 | ) 56 | ], 57 | )) 58 | ], 59 | ), 60 | ), 61 | Divider( 62 | color: Colors.white.withAlpha(200), 63 | height: 16, 64 | ) 65 | ], 66 | ); 67 | } 68 | 69 | @override 70 | Widget build(BuildContext context) { 71 | return DrawerScaffold( 72 | cornerRadius: 0, 73 | appBar: AppBar( 74 | title: Text("Drawer - Custom Item"), 75 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 76 | drawers: [ 77 | SideDrawer.child( 78 | percentage: 1, 79 | headerView: headerView(context), 80 | animation: false, 81 | alignment: Alignment.topLeft, 82 | color: Theme.of(context).primaryColor, 83 | child: Icon(Icons.ac_unit), 84 | ) 85 | ], 86 | builder: (context, id) => IndexedStack( 87 | index: id, 88 | children: menu.items 89 | .map((e) => Center( 90 | child: Text("Page~${e.title}"), 91 | )) 92 | .toList(), 93 | ), 94 | ); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 3.0.4 2 | * close app on last page 3 | 4 | # 3.0.3 5 | * Add custom pop handler 6 | 7 | # 3.0.2 8 | * Dispose drawer animation when DrawerScaffold call dispose() 9 | * make `drawers` required. 10 | * add `closeOnPopInvoked` parameter to auto close drawer for ios 11 | * optimized code and logic 12 | 13 | # 3.0.1 14 | * Remove unnecessary print 15 | * upgrade dependencies 16 | 17 | # 3.0.0 18 | * Make API Changes compatible with Flutter 3.22.0 19 | * BREAKING CHANGE: Add flutter version constraint to be >=3.22.0. This will break for lower versions of Flutter. 20 | 21 | # 2.4.1 22 | * fix static analysis 23 | 24 | # 2.4.0 25 | * Upgrade flutter sdk 26 | * remove/replace deprecated methods and attributes 27 | 28 | # 2.3.1-dev.1 29 | * Fix MenuController 30 | 31 | # 2.3.0-dev.6 32 | * DrawerScaffold body attribute 33 | 34 | # 2.3.0-dev.5 35 | * Fix State 36 | 37 | # 2.3.0-dev.4 38 | * Fix null-safety 39 | * Fix initial value 40 | 41 | # 2.3.0-dev.3 42 | * Make **SideDrawer.count()** as **static method** 43 | * Uncontrol SideDrawer 44 | 45 | # 2.3.0-dev.2 46 | * Fix function type mismatch 47 | 48 | # 2.3.0-dev.1 49 | * new ClassName.identifier: **SideDrawer.count()**, **SideDrawer.child()** and **SideDrawer.custom()** 50 | 51 | # 2.3.0-dev 52 | * peek menu 53 | * hideOnItemPressed 54 | 55 | # 2.2.1 56 | * withSafeArea attribute 57 | 58 | # 2.2.0 59 | * Fix itemBuilder with animation 60 | 61 | # 2.1.2 62 | * Set/assign/copy missing attribute from **AppBar** 63 | 64 | # 2.1.1 65 | * Change appBar parameter type to **PreferredSizeWidget** 66 | 67 | # 2.1.0 68 | * Prefix and suffix attribute 69 | 70 | # 2.0.0+4 71 | * Change minimum version for dart 72 | 73 | # 2.0.0+3 74 | * fix pub.dev score issue 75 | 76 | # 2.0.0+2 77 | * revert pubspec 78 | 79 | # 2.0.0+1 80 | * fix pub.dev issue 81 | 82 | # 2.0.0 83 | * Migrate to null safety 84 | * add **backgroundColor** parameter 85 | * change **mainDrawer** to defaultDirection 86 | * remove **contentView** parameter 87 | 88 | # 1.2.2 89 | * Add child option on [MenuScreen] 90 | * Animation fixed 91 | * GlobalKey error fixed 92 | 93 | # 1.2.1 94 | * ```slide``` parameter on SideDrawer as a flag to slide menu with main container while drawer is opening or closing 95 | * Bug fixed 96 | 97 | # 1.1.4 98 | # 1.1.3 99 | * Listener for onSlide, onOpened and onClosed 100 | 101 | # 1.1.2 102 | * Supress deprecated warning 103 | 104 | # 1.1.1 105 | * Supress deprecated warning 106 | 107 | # 1.1.0 108 | * Web support 109 | 110 | # 1.0.4 111 | * Duration & Curve variable on SideDrawer 112 | 113 | # 1.0.3 114 | * Reuse controller when scaffold config update 115 | * Add elevation & corner radius config on SideDrawer 116 | * Add more example 117 | * **Bug fixed** 118 | 119 | # 1.0.2 120 | * 3D-effect 121 | 122 | # 1.0.1 123 | * add more **Scaffold** config 124 | 125 | # 1.0.0 126 | * Replace **AppBarProps** with **AppBar** Widget 127 | * Multi-drawer 128 | * Right Drawer 129 | 130 | # 0.0.10 131 | * Floating action button with location and animator 132 | * Bottom navigation bar 133 | * Extended body 134 | 135 | # 0.0.9 136 | * Added support for AndroidX 137 | 138 | # 0.0.7 139 | * Add icon parameter on MenuItem 140 | * Support custom MenuItem widget 141 | * Add drawer controller 142 | * Add footer view option 143 | 144 | # 0.0.6 145 | * Drawer absorb gesture, if open 146 | 147 | # 0.0.5 148 | * Handle back button event for Android device 149 | * Add corner radius constraint 150 | * Add content shadow constraint 151 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_slide_with_footer.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior_example/menus/main.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:drawerbehavior/drawerbehavior.dart'; 4 | 5 | class DrawerSlideWithFooter extends StatefulWidget { 6 | const DrawerSlideWithFooter({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerSlideWithFooterState(); 10 | } 11 | 12 | class _DrawerSlideWithFooterState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | Widget footerView(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Divider( 25 | color: Colors.white.withAlpha(200), 26 | height: 16, 27 | ), 28 | Container( 29 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 30 | child: Row( 31 | children: [ 32 | Container( 33 | width: 48.0, 34 | height: 48.0, 35 | decoration: BoxDecoration( 36 | shape: BoxShape.circle, 37 | image: DecorationImage( 38 | fit: BoxFit.fill, 39 | image: AssetImage("assets/user1.jpg")))), 40 | Container( 41 | margin: EdgeInsets.only(left: 16), 42 | child: Column( 43 | mainAxisAlignment: MainAxisAlignment.start, 44 | crossAxisAlignment: CrossAxisAlignment.start, 45 | children: [ 46 | Text( 47 | "John Witch", 48 | style: Theme.of(context) 49 | .textTheme 50 | .titleMedium 51 | ?.copyWith(color: Colors.white), 52 | ), 53 | Text( 54 | "test123@gmail.com", 55 | style: Theme.of(context) 56 | .textTheme 57 | .titleSmall 58 | ?.copyWith(color: Colors.white.withAlpha(200)), 59 | ) 60 | ], 61 | )) 62 | ], 63 | ), 64 | ) 65 | ], 66 | ); 67 | } 68 | 69 | @override 70 | Widget build(BuildContext context) { 71 | return DrawerScaffold( 72 | cornerRadius: 0, 73 | appBar: AppBar( 74 | title: Text("Drawer - with Footer"), 75 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 76 | drawers: [ 77 | SideDrawer( 78 | percentage: 1, 79 | menu: menu, 80 | footerView: footerView(context), 81 | animation: false, 82 | alignment: Alignment.topLeft, 83 | color: Theme.of(context).primaryColor, 84 | selectedItemId: selectedMenuItemId, 85 | onMenuItemSelected: (itemId) { 86 | setState(() { 87 | selectedMenuItemId = itemId; 88 | }); 89 | }, 90 | ) 91 | ], 92 | builder: (context, id) => IndexedStack( 93 | index: id, 94 | children: menu.items 95 | .map((e) => Center( 96 | child: Text("Page~${e.title}"), 97 | )) 98 | .toList(), 99 | ), 100 | ); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /example/windows/runner/Runner.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #pragma code_page(65001) 4 | #include "resource.h" 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include "winres.h" 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (United States) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""winres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Icon 51 | // 52 | 53 | // Icon with lowest ID value placed first to ensure application icon 54 | // remains consistent on all systems. 55 | IDI_APP_ICON ICON "resources\\app_icon.ico" 56 | 57 | 58 | ///////////////////////////////////////////////////////////////////////////// 59 | // 60 | // Version 61 | // 62 | 63 | #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) 64 | #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0,0 67 | #endif 68 | 69 | #if defined(FLUTTER_VERSION) 70 | #define VERSION_AS_STRING FLUTTER_VERSION 71 | #else 72 | #define VERSION_AS_STRING "1.0.0" 73 | #endif 74 | 75 | VS_VERSION_INFO VERSIONINFO 76 | FILEVERSION VERSION_AS_NUMBER 77 | PRODUCTVERSION VERSION_AS_NUMBER 78 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 79 | #ifdef _DEBUG 80 | FILEFLAGS VS_FF_DEBUG 81 | #else 82 | FILEFLAGS 0x0L 83 | #endif 84 | FILEOS VOS__WINDOWS32 85 | FILETYPE VFT_APP 86 | FILESUBTYPE 0x0L 87 | BEGIN 88 | BLOCK "StringFileInfo" 89 | BEGIN 90 | BLOCK "040904e4" 91 | BEGIN 92 | VALUE "CompanyName", "com.example" "\0" 93 | VALUE "FileDescription", "example" "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "example.exe" "\0" 98 | VALUE "ProductName", "example" "\0" 99 | VALUE "ProductVersion", VERSION_AS_STRING "\0" 100 | END 101 | END 102 | BLOCK "VarFileInfo" 103 | BEGIN 104 | VALUE "Translation", 0x409, 1252 105 | END 106 | END 107 | 108 | #endif // English (United States) resources 109 | ///////////////////////////////////////////////////////////////////////////// 110 | 111 | 112 | 113 | #ifndef APSTUDIO_INVOKED 114 | ///////////////////////////////////////////////////////////////////////////// 115 | // 116 | // Generated from the TEXTINCLUDE 3 resource. 117 | // 118 | 119 | 120 | ///////////////////////////////////////////////////////////////////////////// 121 | #endif // not APSTUDIO_INVOKED 122 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_slide_with_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior_example/menus/main.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:drawerbehavior/drawerbehavior.dart'; 4 | 5 | class DrawerSlideWithHeader extends StatefulWidget { 6 | const DrawerSlideWithHeader({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerSlideWithHeaderState(); 10 | } 11 | 12 | class _DrawerSlideWithHeaderState extends State { 13 | int? selectedMenuItemId; 14 | 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | Widget headerView(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Container( 25 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 26 | child: Row( 27 | children: [ 28 | Container( 29 | width: 48.0, 30 | height: 48.0, 31 | decoration: BoxDecoration( 32 | shape: BoxShape.circle, 33 | image: DecorationImage( 34 | fit: BoxFit.fill, 35 | image: AssetImage("assets/user1.jpg")))), 36 | Container( 37 | margin: EdgeInsets.only(left: 16), 38 | child: Column( 39 | mainAxisAlignment: MainAxisAlignment.start, 40 | crossAxisAlignment: CrossAxisAlignment.start, 41 | children: [ 42 | Text( 43 | "John Witch", 44 | style: Theme.of(context) 45 | .textTheme 46 | .titleMedium 47 | ?.copyWith(color: Colors.white), 48 | ), 49 | Text( 50 | "test123@gmail.com", 51 | style: Theme.of(context) 52 | .textTheme 53 | .titleSmall 54 | ?.copyWith(color: Colors.white.withAlpha(200)), 55 | ) 56 | ], 57 | )) 58 | ], 59 | ), 60 | ), 61 | Divider( 62 | color: Colors.white.withAlpha(200), 63 | height: 16, 64 | ) 65 | ], 66 | ); 67 | } 68 | 69 | @override 70 | Widget build(BuildContext context) { 71 | return DrawerScaffold( 72 | cornerRadius: 0, 73 | appBar: AppBar( 74 | title: Text("Drawer - with Header"), 75 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 76 | drawers: [ 77 | SideDrawer( 78 | // withSafeAre: false, 79 | percentage: 1, 80 | menu: menu, 81 | headerView: headerView(context), 82 | animation: false, 83 | alignment: Alignment.topLeft, 84 | color: Theme.of(context).primaryColor, 85 | selectedItemId: selectedMenuItemId, 86 | onMenuItemSelected: (itemId) { 87 | setState(() { 88 | selectedMenuItemId = itemId; 89 | }); 90 | }, 91 | ) 92 | ], 93 | builder: (context, id) => IndexedStack( 94 | index: id, 95 | children: menu.items 96 | .map((e) => Center( 97 | child: Text("Page~${e.title}"), 98 | )) 99 | .toList(), 100 | ), 101 | ); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_WIN32_WINDOW_H_ 2 | #define RUNNER_WIN32_WINDOW_H_ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | // A class abstraction for a high DPI-aware Win32 Window. Intended to be 11 | // inherited from by classes that wish to specialize with custom 12 | // rendering and input handling 13 | class Win32Window { 14 | public: 15 | struct Point { 16 | unsigned int x; 17 | unsigned int y; 18 | Point(unsigned int x, unsigned int y) : x(x), y(y) {} 19 | }; 20 | 21 | struct Size { 22 | unsigned int width; 23 | unsigned int height; 24 | Size(unsigned int width, unsigned int height) 25 | : width(width), height(height) {} 26 | }; 27 | 28 | Win32Window(); 29 | virtual ~Win32Window(); 30 | 31 | // Creates a win32 window with |title| that is positioned and sized using 32 | // |origin| and |size|. New windows are created on the default monitor. Window 33 | // sizes are specified to the OS in physical pixels, hence to ensure a 34 | // consistent size this function will scale the inputted width and height as 35 | // as appropriate for the default monitor. The window is invisible until 36 | // |Show| is called. Returns true if the window was created successfully. 37 | bool Create(const std::wstring& title, const Point& origin, const Size& size); 38 | 39 | // Show the current window. Returns true if the window was successfully shown. 40 | bool Show(); 41 | 42 | // Release OS resources associated with window. 43 | void Destroy(); 44 | 45 | // Inserts |content| into the window tree. 46 | void SetChildContent(HWND content); 47 | 48 | // Returns the backing Window handle to enable clients to set icon and other 49 | // window properties. Returns nullptr if the window has been destroyed. 50 | HWND GetHandle(); 51 | 52 | // If true, closing this window will quit the application. 53 | void SetQuitOnClose(bool quit_on_close); 54 | 55 | // Return a RECT representing the bounds of the current client area. 56 | RECT GetClientArea(); 57 | 58 | protected: 59 | // Processes and route salient window messages for mouse handling, 60 | // size change and DPI. Delegates handling of these to member overloads that 61 | // inheriting classes can handle. 62 | virtual LRESULT MessageHandler(HWND window, 63 | UINT const message, 64 | WPARAM const wparam, 65 | LPARAM const lparam) noexcept; 66 | 67 | // Called when CreateAndShow is called, allowing subclass window-related 68 | // setup. Subclasses should return false if setup fails. 69 | virtual bool OnCreate(); 70 | 71 | // Called when Destroy is called. 72 | virtual void OnDestroy(); 73 | 74 | private: 75 | friend class WindowClassRegistrar; 76 | 77 | // OS callback called by message pump. Handles the WM_NCCREATE message which 78 | // is passed when the non-client area is being created and enables automatic 79 | // non-client DPI scaling so that the non-client area automatically 80 | // responds to changes in DPI. All other messages are handled by 81 | // MessageHandler. 82 | static LRESULT CALLBACK WndProc(HWND const window, 83 | UINT const message, 84 | WPARAM const wparam, 85 | LPARAM const lparam) noexcept; 86 | 87 | // Retrieves a class instance pointer for |window| 88 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 89 | 90 | // Update the window frame's theme to match the system theme. 91 | static void UpdateTheme(HWND const window); 92 | 93 | bool quit_on_close_ = false; 94 | 95 | // window handle for top level window. 96 | HWND window_handle_ = nullptr; 97 | 98 | // window handle for hosted content. 99 | HWND child_content_ = nullptr; 100 | }; 101 | 102 | #endif // RUNNER_WIN32_WINDOW_H_ 103 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_custom_item_by_count.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | class DrawerCustomItemByCount extends StatefulWidget { 5 | const DrawerCustomItemByCount({Key? key}) : super(key: key); 6 | 7 | @override 8 | State createState() => 9 | _DrawerCustomItemByCountState(); 10 | } 11 | 12 | class _DrawerCustomItemByCountState extends State { 13 | final DrawerScaffoldController controller = DrawerScaffoldController(); 14 | @override 15 | void initState() { 16 | super.initState(); 17 | } 18 | 19 | Widget headerView(BuildContext context) { 20 | return Column( 21 | children: [ 22 | Container( 23 | width: 400, 24 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 25 | child: Row( 26 | children: [ 27 | Container( 28 | width: 48.0, 29 | height: 48.0, 30 | decoration: BoxDecoration( 31 | shape: BoxShape.circle, 32 | image: DecorationImage( 33 | fit: BoxFit.fill, 34 | image: AssetImage("assets/user1.jpg")))), 35 | Container( 36 | margin: EdgeInsets.only(left: 16), 37 | child: Column( 38 | mainAxisAlignment: MainAxisAlignment.start, 39 | crossAxisAlignment: CrossAxisAlignment.start, 40 | children: [ 41 | Text( 42 | "John Witch", 43 | style: Theme.of(context) 44 | .textTheme 45 | .titleMedium 46 | ?.copyWith(color: Colors.white), 47 | ), 48 | Text( 49 | "test123@gmail.com", 50 | style: Theme.of(context) 51 | .textTheme 52 | .titleSmall 53 | ?.copyWith(color: Colors.white.withAlpha(200)), 54 | ) 55 | ], 56 | )) 57 | ], 58 | ), 59 | ), 60 | Divider( 61 | color: Colors.white.withAlpha(200), 62 | height: 16, 63 | ) 64 | ], 65 | ); 66 | } 67 | 68 | int itemCount = 10; 69 | @override 70 | Widget build(BuildContext context) { 71 | return DrawerScaffold( 72 | controller: controller, 73 | cornerRadius: 0, 74 | appBar: AppBar( 75 | title: Text("Drawer - Custom Item by Count"), 76 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 77 | drawers: [ 78 | SideDrawer.count( 79 | selectedItemId: 0, 80 | itemCount: itemCount, 81 | percentage: 1, 82 | headerView: headerView(context), 83 | alignment: Alignment.topLeft, 84 | color: Theme.of(context).primaryColor, 85 | builder: (BuildContext context, int index, bool isSelected) { 86 | return Container( 87 | color: isSelected 88 | ? Theme.of(context) 89 | .colorScheme 90 | .secondary 91 | .withAlpha((255 * 0.7).toInt()) 92 | : Colors.transparent, 93 | padding: EdgeInsets.fromLTRB(24, 16, 24, 16), 94 | child: Text( 95 | "Item $index", 96 | style: Theme.of(context).textTheme.titleMedium?.copyWith( 97 | color: isSelected ? Colors.black87 : Colors.white70), 98 | ), 99 | ); 100 | }, 101 | ) 102 | ], 103 | builder: (context, id) => IndexedStack( 104 | index: id, 105 | children: List.generate( 106 | itemCount, 107 | (e) => Center( 108 | child: Text("Page~$e"), 109 | )).toList(), 110 | ), 111 | ); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /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, "example"); 44 | gtk_header_bar_set_show_close_button(header_bar, TRUE); 45 | gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); 46 | } else { 47 | gtk_window_set_title(window, "example"); 48 | } 49 | 50 | gtk_window_set_default_size(window, 1280, 720); 51 | gtk_widget_show(GTK_WIDGET(window)); 52 | 53 | g_autoptr(FlDartProject) project = fl_dart_project_new(); 54 | fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); 55 | 56 | FlView* view = fl_view_new(project); 57 | gtk_widget_show(GTK_WIDGET(view)); 58 | gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); 59 | 60 | fl_register_plugins(FL_PLUGIN_REGISTRY(view)); 61 | 62 | gtk_widget_grab_focus(GTK_WIDGET(view)); 63 | } 64 | 65 | // Implements GApplication::local_command_line. 66 | static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { 67 | MyApplication* self = MY_APPLICATION(application); 68 | // Strip out the first argument as it is the binary name. 69 | self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); 70 | 71 | g_autoptr(GError) error = nullptr; 72 | if (!g_application_register(application, nullptr, &error)) { 73 | g_warning("Failed to register: %s", error->message); 74 | *exit_status = 1; 75 | return TRUE; 76 | } 77 | 78 | g_application_activate(application); 79 | *exit_status = 0; 80 | 81 | return TRUE; 82 | } 83 | 84 | // Implements GObject::dispose. 85 | static void my_application_dispose(GObject* object) { 86 | MyApplication* self = MY_APPLICATION(object); 87 | g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); 88 | G_OBJECT_CLASS(my_application_parent_class)->dispose(object); 89 | } 90 | 91 | static void my_application_class_init(MyApplicationClass* klass) { 92 | G_APPLICATION_CLASS(klass)->activate = my_application_activate; 93 | G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; 94 | G_OBJECT_CLASS(klass)->dispose = my_application_dispose; 95 | } 96 | 97 | static void my_application_init(MyApplication* self) {} 98 | 99 | MyApplication* my_application_new() { 100 | return MY_APPLICATION(g_object_new(my_application_get_type(), 101 | "application-id", APPLICATION_ID, 102 | "flags", G_APPLICATION_NON_UNIQUE, 103 | nullptr)); 104 | } 105 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_slide_custom_appbar.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerSlideCustomAppBar extends StatefulWidget { 6 | const DrawerSlideCustomAppBar({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => 10 | _DrawerSlideCustomAppBarState(); 11 | } 12 | 13 | class _DrawerSlideCustomAppBarState extends State { 14 | int? selectedMenuItemId; 15 | 16 | @override 17 | void initState() { 18 | selectedMenuItemId = menu.items[0].id; 19 | super.initState(); 20 | } 21 | 22 | Widget headerView(BuildContext context) { 23 | return Column( 24 | children: [ 25 | Container( 26 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 27 | child: Row( 28 | children: [ 29 | Container( 30 | width: 48.0, 31 | height: 48.0, 32 | decoration: BoxDecoration( 33 | shape: BoxShape.circle, 34 | image: DecorationImage( 35 | fit: BoxFit.fill, 36 | image: AssetImage("assets/user1.jpg")))), 37 | Container( 38 | margin: EdgeInsets.only(left: 16), 39 | child: Column( 40 | mainAxisAlignment: MainAxisAlignment.start, 41 | crossAxisAlignment: CrossAxisAlignment.start, 42 | children: [ 43 | Text( 44 | "John Witch", 45 | style: Theme.of(context) 46 | .textTheme 47 | .titleMedium 48 | ?.copyWith(color: Colors.white), 49 | ), 50 | Text( 51 | "test123@gmail.com", 52 | style: Theme.of(context) 53 | .textTheme 54 | .titleSmall 55 | ?.copyWith(color: Colors.white.withAlpha(200)), 56 | ) 57 | ], 58 | )) 59 | ], 60 | ), 61 | ), 62 | Divider( 63 | color: Colors.white.withAlpha(200), 64 | height: 16, 65 | ) 66 | ], 67 | ); 68 | } 69 | 70 | DrawerScaffoldController controller = DrawerScaffoldController(); 71 | 72 | buildDrawer(BuildContext context) { 73 | return DrawerScaffold( 74 | controller: controller, 75 | cornerRadius: 0, 76 | // appBar: AppBar( 77 | // title: Text("Drawer - Slide with Custom AppBar"), 78 | // actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 79 | drawers: [ 80 | SideDrawer( 81 | percentage: 1, 82 | menu: menu, 83 | headerView: headerView(context), 84 | animation: false, 85 | alignment: Alignment.topLeft, 86 | color: Theme.of(context).primaryColor, 87 | selectedItemId: selectedMenuItemId, 88 | onMenuItemSelected: (itemId) { 89 | setState(() { 90 | selectedMenuItemId = itemId; 91 | }); 92 | }, 93 | ) 94 | ], 95 | builder: (context, id) => Scaffold( 96 | appBar: AppBar( 97 | title: Text("Drawer - Slide with Custom AppBar"), 98 | leading: IconButton( 99 | icon: Icon(Icons.menu), 100 | onPressed: () { 101 | controller.toggle(); 102 | }), 103 | ), 104 | body: IndexedStack( 105 | index: id, 106 | children: menu.items 107 | .map((e) => Center( 108 | child: Text("Page~${e.title}"), 109 | )) 110 | .toList(), 111 | ), 112 | ), 113 | ); 114 | } 115 | 116 | @override 117 | Widget build(BuildContext context) { 118 | return buildDrawer(context); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # This file controls Flutter-level build steps. It should not be edited. 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 5 | 6 | # Configuration provided via flutter tool. 7 | include(${EPHEMERAL_DIR}/generated_config.cmake) 8 | 9 | # TODO: Move the rest of this into files in ephemeral. See 10 | # https://github.com/flutter/flutter/issues/57146. 11 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 12 | 13 | # Set fallback configurations for older versions of the flutter tool. 14 | if (NOT DEFINED FLUTTER_TARGET_PLATFORM) 15 | set(FLUTTER_TARGET_PLATFORM "windows-x64") 16 | endif() 17 | 18 | # === Flutter Library === 19 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 20 | 21 | # Published to parent scope for install step. 22 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 23 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 24 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 25 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 26 | 27 | list(APPEND FLUTTER_LIBRARY_HEADERS 28 | "flutter_export.h" 29 | "flutter_windows.h" 30 | "flutter_messenger.h" 31 | "flutter_plugin_registrar.h" 32 | "flutter_texture_registrar.h" 33 | ) 34 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 35 | add_library(flutter INTERFACE) 36 | target_include_directories(flutter INTERFACE 37 | "${EPHEMERAL_DIR}" 38 | ) 39 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 40 | add_dependencies(flutter flutter_assemble) 41 | 42 | # === Wrapper === 43 | list(APPEND CPP_WRAPPER_SOURCES_CORE 44 | "core_implementations.cc" 45 | "standard_codec.cc" 46 | ) 47 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 48 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 49 | "plugin_registrar.cc" 50 | ) 51 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 52 | list(APPEND CPP_WRAPPER_SOURCES_APP 53 | "flutter_engine.cc" 54 | "flutter_view_controller.cc" 55 | ) 56 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 57 | 58 | # Wrapper sources needed for a plugin. 59 | add_library(flutter_wrapper_plugin STATIC 60 | ${CPP_WRAPPER_SOURCES_CORE} 61 | ${CPP_WRAPPER_SOURCES_PLUGIN} 62 | ) 63 | apply_standard_settings(flutter_wrapper_plugin) 64 | set_target_properties(flutter_wrapper_plugin PROPERTIES 65 | POSITION_INDEPENDENT_CODE ON) 66 | set_target_properties(flutter_wrapper_plugin PROPERTIES 67 | CXX_VISIBILITY_PRESET hidden) 68 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 69 | target_include_directories(flutter_wrapper_plugin PUBLIC 70 | "${WRAPPER_ROOT}/include" 71 | ) 72 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 73 | 74 | # Wrapper sources needed for the runner. 75 | add_library(flutter_wrapper_app STATIC 76 | ${CPP_WRAPPER_SOURCES_CORE} 77 | ${CPP_WRAPPER_SOURCES_APP} 78 | ) 79 | apply_standard_settings(flutter_wrapper_app) 80 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 81 | target_include_directories(flutter_wrapper_app PUBLIC 82 | "${WRAPPER_ROOT}/include" 83 | ) 84 | add_dependencies(flutter_wrapper_app flutter_assemble) 85 | 86 | # === Flutter tool backend === 87 | # _phony_ is a non-existent file to force this command to run every time, 88 | # since currently there's no way to get a full input/output list from the 89 | # flutter tool. 90 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 91 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 92 | add_custom_command( 93 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 94 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 95 | ${CPP_WRAPPER_SOURCES_APP} 96 | ${PHONY_OUTPUT} 97 | COMMAND ${CMAKE_COMMAND} -E env 98 | ${FLUTTER_TOOL_ENVIRONMENT} 99 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 100 | ${FLUTTER_TARGET_PLATFORM} $ 101 | VERBATIM 102 | ) 103 | add_custom_target(flutter_assemble DEPENDS 104 | "${FLUTTER_LIBRARY}" 105 | ${FLUTTER_LIBRARY_HEADERS} 106 | ${CPP_WRAPPER_SOURCES_CORE} 107 | ${CPP_WRAPPER_SOURCES_PLUGIN} 108 | ${CPP_WRAPPER_SOURCES_APP} 109 | ) 110 | -------------------------------------------------------------------------------- /example/lib/pages/drawer_custom_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior_example/menus/main.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class DrawerCustomItem extends StatefulWidget { 6 | const DrawerCustomItem({Key? key}) : super(key: key); 7 | 8 | @override 9 | State createState() => _DrawerCustomItemState(); 10 | } 11 | 12 | class _DrawerCustomItemState extends State { 13 | int? selectedMenuItemId; 14 | final DrawerScaffoldController controller = DrawerScaffoldController(); 15 | @override 16 | void initState() { 17 | selectedMenuItemId = menu.items[0].id; 18 | super.initState(); 19 | } 20 | 21 | Widget headerView(BuildContext context) { 22 | return Column( 23 | children: [ 24 | Container( 25 | width: 400, 26 | padding: EdgeInsets.fromLTRB(16, 12, 16, 0), 27 | child: Row( 28 | children: [ 29 | Container( 30 | width: 48.0, 31 | height: 48.0, 32 | decoration: BoxDecoration( 33 | shape: BoxShape.circle, 34 | image: DecorationImage( 35 | fit: BoxFit.fill, 36 | image: AssetImage("assets/user1.jpg")))), 37 | Container( 38 | margin: EdgeInsets.only(left: 16), 39 | child: Column( 40 | mainAxisAlignment: MainAxisAlignment.start, 41 | crossAxisAlignment: CrossAxisAlignment.start, 42 | children: [ 43 | Text( 44 | "John Witch", 45 | style: Theme.of(context) 46 | .textTheme 47 | .titleMedium 48 | ?.copyWith(color: Colors.white), 49 | ), 50 | Text( 51 | "test123@gmail.com", 52 | style: Theme.of(context) 53 | .textTheme 54 | .titleSmall 55 | ?.copyWith(color: Colors.white.withAlpha(200)), 56 | ) 57 | ], 58 | )) 59 | ], 60 | ), 61 | ), 62 | Divider( 63 | color: Colors.white.withAlpha(200), 64 | height: 16, 65 | ) 66 | ], 67 | ); 68 | } 69 | 70 | @override 71 | Widget build(BuildContext context) { 72 | return DrawerScaffold( 73 | controller: controller, 74 | cornerRadius: 0, 75 | appBar: AppBar( 76 | title: Text("Drawer - Custom Item"), 77 | actions: [IconButton(icon: Icon(Icons.add), onPressed: () {})]), 78 | drawers: [ 79 | SideDrawer( 80 | percentage: 1, 81 | menu: menu, 82 | headerView: headerView(context), 83 | alignment: Alignment.topLeft, 84 | color: Theme.of(context).primaryColor, 85 | selectedItemId: selectedMenuItemId, 86 | itemBuilder: 87 | (BuildContext context, MenuItem menuItem, bool isSelected) { 88 | return Container( 89 | color: isSelected 90 | ? Theme.of(context) 91 | .colorScheme 92 | .secondary 93 | .withAlpha((255 * 0.7).toInt()) 94 | : Colors.transparent, 95 | padding: EdgeInsets.fromLTRB(24, 16, 24, 16), 96 | child: Text( 97 | menuItem.title, 98 | style: Theme.of(context).textTheme.titleMedium?.copyWith( 99 | color: isSelected ? Colors.black87 : Colors.white70), 100 | ), 101 | ); 102 | }, 103 | onMenuItemSelected: (itemId) { 104 | setState(() { 105 | selectedMenuItemId = itemId; 106 | }); 107 | }, 108 | ) 109 | ], 110 | builder: (context, id) => IndexedStack( 111 | index: id, 112 | children: menu.items 113 | .map((e) => Center( 114 | child: Text("Page~${e.title}"), 115 | )) 116 | .toList(), 117 | ), 118 | ); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.14) 3 | project(example LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "example") 8 | 9 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 10 | # versions of CMake. 11 | cmake_policy(VERSION 3.14...3.25) 12 | 13 | # Define build configuration option. 14 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 15 | if(IS_MULTICONFIG) 16 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 17 | CACHE STRING "" FORCE) 18 | else() 19 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 20 | set(CMAKE_BUILD_TYPE "Debug" CACHE 21 | STRING "Flutter build mode" FORCE) 22 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 23 | "Debug" "Profile" "Release") 24 | endif() 25 | endif() 26 | # Define settings for the Profile build mode. 27 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 28 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 29 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 30 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 31 | 32 | # Use Unicode for all projects. 33 | add_definitions(-DUNICODE -D_UNICODE) 34 | 35 | # Compilation settings that should be applied to most targets. 36 | # 37 | # Be cautious about adding new options here, as plugins use this function by 38 | # default. In most cases, you should add new options to specific targets instead 39 | # of modifying this function. 40 | function(APPLY_STANDARD_SETTINGS TARGET) 41 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 42 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 43 | target_compile_options(${TARGET} PRIVATE /EHsc) 44 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 45 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 46 | endfunction() 47 | 48 | # Flutter library and tool build rules. 49 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 50 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 51 | 52 | # Application build; see runner/CMakeLists.txt. 53 | add_subdirectory("runner") 54 | 55 | 56 | # Generated plugin build rules, which manage building the plugins and adding 57 | # them to the application. 58 | include(flutter/generated_plugins.cmake) 59 | 60 | 61 | # === Installation === 62 | # Support files are copied into place next to the executable, so that it can 63 | # run in place. This is done instead of making a separate bundle (as on Linux) 64 | # so that building and running from within Visual Studio will work. 65 | set(BUILD_BUNDLE_DIR "$") 66 | # Make the "install" step default, as it's required to run. 67 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 68 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 69 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 70 | endif() 71 | 72 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 73 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 74 | 75 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 76 | COMPONENT Runtime) 77 | 78 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 79 | COMPONENT Runtime) 80 | 81 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 82 | COMPONENT Runtime) 83 | 84 | if(PLUGIN_BUNDLED_LIBRARIES) 85 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 86 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 87 | COMPONENT Runtime) 88 | endif() 89 | 90 | # Copy the native assets provided by the build.dart from all packages. 91 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") 92 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 93 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 94 | COMPONENT Runtime) 95 | 96 | # Fully re-copy the assets directory on each build to avoid having stale files 97 | # from a previous install. 98 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 99 | install(CODE " 100 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 101 | " COMPONENT Runtime) 102 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 103 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 104 | 105 | # Install the AOT library on non-Debug builds only. 106 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 107 | CONFIGURATIONS Profile;Release 108 | COMPONENT Runtime) 109 | -------------------------------------------------------------------------------- /example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Project-level configuration. 2 | cmake_minimum_required(VERSION 3.10) 3 | project(runner LANGUAGES CXX) 4 | 5 | # The name of the executable created for the application. Change this to change 6 | # the on-disk name of your application. 7 | set(BINARY_NAME "example") 8 | # The unique GTK application identifier for this application. See: 9 | # https://wiki.gnome.org/HowDoI/ChooseApplicationID 10 | set(APPLICATION_ID "com.example.example") 11 | 12 | # Explicitly opt in to modern CMake behaviors to avoid warnings with recent 13 | # versions of CMake. 14 | cmake_policy(SET CMP0063 NEW) 15 | 16 | # Load bundled libraries from the lib/ directory relative to the binary. 17 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 18 | 19 | # Root filesystem for cross-building. 20 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 21 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 22 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 23 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 24 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 25 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 26 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 27 | endif() 28 | 29 | # Define build configuration options. 30 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 31 | set(CMAKE_BUILD_TYPE "Debug" CACHE 32 | STRING "Flutter build mode" FORCE) 33 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 34 | "Debug" "Profile" "Release") 35 | endif() 36 | 37 | # Compilation settings that should be applied to most targets. 38 | # 39 | # Be cautious about adding new options here, as plugins use this function by 40 | # default. In most cases, you should add new options to specific targets instead 41 | # of modifying this function. 42 | function(APPLY_STANDARD_SETTINGS TARGET) 43 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 44 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 45 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 46 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 47 | endfunction() 48 | 49 | # Flutter library and tool build rules. 50 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 51 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 52 | 53 | # System-level dependencies. 54 | find_package(PkgConfig REQUIRED) 55 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 56 | 57 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 58 | 59 | # Define the application target. To change its name, change BINARY_NAME above, 60 | # not the value here, or `flutter run` will no longer work. 61 | # 62 | # Any new source files that you add to the application should be added here. 63 | add_executable(${BINARY_NAME} 64 | "main.cc" 65 | "my_application.cc" 66 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 67 | ) 68 | 69 | # Apply the standard set of build settings. This can be removed for applications 70 | # that need different build settings. 71 | apply_standard_settings(${BINARY_NAME}) 72 | 73 | # Add dependency libraries. Add any application-specific dependencies here. 74 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 75 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 76 | 77 | # Run the Flutter tool portions of the build. This must not be removed. 78 | add_dependencies(${BINARY_NAME} flutter_assemble) 79 | 80 | # Only the install-generated bundle's copy of the executable will launch 81 | # correctly, since the resources must in the right relative locations. To avoid 82 | # people trying to run the unbundled copy, put it in a subdirectory instead of 83 | # the default top-level location. 84 | set_target_properties(${BINARY_NAME} 85 | PROPERTIES 86 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 87 | ) 88 | 89 | 90 | # Generated plugin build rules, which manage building the plugins and adding 91 | # them to the application. 92 | include(flutter/generated_plugins.cmake) 93 | 94 | 95 | # === Installation === 96 | # By default, "installing" just makes a relocatable bundle in the build 97 | # directory. 98 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 99 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 100 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 101 | endif() 102 | 103 | # Start with a clean build bundle directory every time. 104 | install(CODE " 105 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 106 | " COMPONENT Runtime) 107 | 108 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 109 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 110 | 111 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 112 | COMPONENT Runtime) 113 | 114 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 115 | COMPONENT Runtime) 116 | 117 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 118 | COMPONENT Runtime) 119 | 120 | foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) 121 | install(FILES "${bundled_library}" 122 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 123 | COMPONENT Runtime) 124 | endforeach(bundled_library) 125 | 126 | # Copy the native assets provided by the build.dart from all packages. 127 | set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") 128 | install(DIRECTORY "${NATIVE_ASSETS_DIR}" 129 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 130 | COMPONENT Runtime) 131 | 132 | # Fully re-copy the assets directory on each build to avoid having stale files 133 | # from a previous install. 134 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 135 | install(CODE " 136 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 137 | " COMPONENT Runtime) 138 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 139 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 140 | 141 | # Install the AOT library on non-Debug builds only. 142 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 143 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 144 | COMPONENT Runtime) 145 | endif() 146 | -------------------------------------------------------------------------------- /lib/src/builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:drawerbehavior/drawerbehavior.dart'; 2 | import 'package:drawerbehavior/src/menu_list.dart'; 3 | import 'package:flutter/material.dart' hide MenuController; 4 | 5 | typedef SideDrawerItemBuilder = Function( 6 | BuildContext context, MenuItem menuItem, bool selected); 7 | 8 | typedef SideDrawerIndexBuilder = Function( 9 | BuildContext context, int index, bool selected); 10 | 11 | abstract class SideDrawerBuilder { 12 | MenuController? _menuController; 13 | SideDrawer? _drawer; 14 | 15 | MenuController? get menuController => _menuController; 16 | 17 | SideDrawer? get drawer => _drawer; 18 | 19 | onSelected(IdType id) { 20 | menuController?.updateValue(id); 21 | drawer?.onMenuItemSelected?.call(id); 22 | if (drawer?.hideOnItemPressed == true) menuController?.close(); 23 | } 24 | 25 | IdType? get selectedId => menuController?.value; 26 | 27 | set(SideDrawer drawer, MenuController? menuController) { 28 | this._menuController = menuController; 29 | this._drawer = drawer; 30 | } 31 | 32 | Widget build(BuildContext context); 33 | Widget buildItem(BuildContext context, ItemType t, bool selected); 34 | } 35 | 36 | class MenuSideDrawerBuilder 37 | extends SideDrawerBuilder { 38 | final SideDrawerItemBuilder? builder; 39 | final Menu menu; 40 | 41 | MenuSideDrawerBuilder( 42 | this.menu, 43 | this.builder, 44 | ); 45 | @override 46 | Widget buildItem(BuildContext context, MenuItem t, bool selected) { 47 | return builder?.call(context, t, selected); 48 | } 49 | 50 | bool get useAnimation => 51 | drawer?.animation == true && drawer?.peekMenu != true; 52 | 53 | Widget buildListItem( 54 | BuildContext context, 55 | MenuItem item, 56 | double animationIntervalStart, 57 | double animationIntervalEnd, 58 | int millis, 59 | double maxDuration, 60 | ) { 61 | final isSelected = item.id == selectedId; 62 | Color selectorColor = 63 | drawer?.selectorColor ?? Theme.of(context).colorScheme.secondary; 64 | TextStyle? textStyle = drawer?.textStyle ?? 65 | Theme.of(context).textTheme.titleMedium?.copyWith( 66 | color: (drawer?.color.computeLuminance() ?? 0) < 0.5 67 | ? Colors.white 68 | : Colors.black); 69 | 70 | Widget listItem = InkWell( 71 | child: builder == null 72 | ? MenuListItem( 73 | padding: drawer?.peekMenu == true 74 | ? EdgeInsets.zero 75 | : const EdgeInsets.only(left: 32.0), 76 | direction: drawer?.direction ?? Direction.left, 77 | title: item.title, 78 | isSelected: isSelected, 79 | selectorColor: selectorColor, 80 | textStyle: item.textStyle ?? textStyle, 81 | menuView: drawer, 82 | width: drawer?.maxSlideAmount(context), 83 | icon: item.icon == null ? item.prefix : Icon(item.icon), 84 | suffix: item.suffix, 85 | drawBorder: !useAnimation) 86 | : Container( 87 | alignment: Alignment.centerLeft, 88 | child: SizedBox( 89 | width: drawer?.maxSlideAmount(context), 90 | child: buildItem(context, item, isSelected), 91 | ), 92 | ), 93 | onTap: () => onSelected(item.id), 94 | ); 95 | 96 | if (useAnimation) { 97 | return AnimatedMenuListItem( 98 | menuState: menuController?.state, 99 | isSelected: isSelected, 100 | duration: Duration(milliseconds: millis), 101 | curve: Interval(animationIntervalStart / maxDuration, 102 | animationIntervalEnd / maxDuration, 103 | curve: Curves.easeOut), 104 | menuListItem: listItem, 105 | ); 106 | } else { 107 | return listItem; 108 | } 109 | } 110 | 111 | @override 112 | Widget build(BuildContext context) { 113 | final animationIntervalDuration = 0.5; 114 | final perListItemDelay = 115 | menuController?.state != MenuState.closing ? 0.15 : 0.0; 116 | final millis = menuController?.state != MenuState.closing 117 | ? 150 * menu.items.length 118 | : 600; 119 | 120 | final maxDuration = 121 | (menu.items.length - 1) * perListItemDelay + animationIntervalDuration; 122 | 123 | int i = 0; 124 | final items = menu.items.map((e) { 125 | final animationIntervalStart = i * perListItemDelay; 126 | final animationIntervalEnd = 127 | animationIntervalStart + animationIntervalDuration; 128 | MenuItem item = menu.items[i]; 129 | i++; 130 | return buildListItem(context, item, animationIntervalStart, 131 | animationIntervalEnd, millis, maxDuration); 132 | }).toList(); 133 | 134 | return Column( 135 | mainAxisSize: MainAxisSize.max, 136 | crossAxisAlignment: CrossAxisAlignment.start, 137 | children: items, 138 | ); 139 | } 140 | } 141 | 142 | class CountSideDrawerBuilder extends SideDrawerBuilder { 143 | final SideDrawerIndexBuilder builder; 144 | final int itemCount; 145 | 146 | CountSideDrawerBuilder( 147 | this.itemCount, 148 | this.builder, 149 | ); 150 | @override 151 | Widget buildItem(BuildContext context, int t, bool selected) { 152 | return builder(context, t, selected); 153 | } 154 | 155 | @override 156 | Widget build(BuildContext context) { 157 | final items = List.generate(itemCount, (e) { 158 | return InkWell( 159 | child: Container( 160 | alignment: Alignment.centerLeft, 161 | child: SizedBox( 162 | width: drawer?.maxSlideAmount(context), 163 | child: buildItem(context, e, selectedId == e), 164 | ), 165 | ), 166 | onTap: () => onSelected(e), 167 | ); 168 | }); 169 | 170 | return Column( 171 | mainAxisSize: MainAxisSize.max, 172 | crossAxisAlignment: CrossAxisAlignment.start, 173 | children: items, 174 | ); 175 | } 176 | } 177 | 178 | class WidgetSideDrawerBuilder extends SideDrawerBuilder { 179 | final Widget child; 180 | 181 | WidgetSideDrawerBuilder( 182 | this.child, 183 | ); 184 | @override 185 | Widget buildItem(BuildContext context, dynamic t, bool selected) { 186 | return child; 187 | } 188 | 189 | @override 190 | Widget build(BuildContext context) { 191 | return Container( 192 | alignment: Alignment.topLeft, 193 | width: drawer?.maxSlideAmount(context), 194 | child: buildItem(context, null, false), 195 | ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.cpp: -------------------------------------------------------------------------------- 1 | #include "win32_window.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "resource.h" 7 | 8 | namespace { 9 | 10 | /// Window attribute that enables dark mode window decorations. 11 | /// 12 | /// Redefined in case the developer's machine has a Windows SDK older than 13 | /// version 10.0.22000.0. 14 | /// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute 15 | #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE 16 | #define DWMWA_USE_IMMERSIVE_DARK_MODE 20 17 | #endif 18 | 19 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; 20 | 21 | /// Registry key for app theme preference. 22 | /// 23 | /// A value of 0 indicates apps should use dark mode. A non-zero or missing 24 | /// value indicates apps should use light mode. 25 | constexpr const wchar_t kGetPreferredBrightnessRegKey[] = 26 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; 27 | constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; 28 | 29 | // The number of Win32Window objects that currently exist. 30 | static int g_active_window_count = 0; 31 | 32 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); 33 | 34 | // Scale helper to convert logical scaler values to physical using passed in 35 | // scale factor 36 | int Scale(int source, double scale_factor) { 37 | return static_cast(source * scale_factor); 38 | } 39 | 40 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. 41 | // This API is only needed for PerMonitor V1 awareness mode. 42 | void EnableFullDpiSupportIfAvailable(HWND hwnd) { 43 | HMODULE user32_module = LoadLibraryA("User32.dll"); 44 | if (!user32_module) { 45 | return; 46 | } 47 | auto enable_non_client_dpi_scaling = 48 | reinterpret_cast( 49 | GetProcAddress(user32_module, "EnableNonClientDpiScaling")); 50 | if (enable_non_client_dpi_scaling != nullptr) { 51 | enable_non_client_dpi_scaling(hwnd); 52 | } 53 | FreeLibrary(user32_module); 54 | } 55 | 56 | } // namespace 57 | 58 | // Manages the Win32Window's window class registration. 59 | class WindowClassRegistrar { 60 | public: 61 | ~WindowClassRegistrar() = default; 62 | 63 | // Returns the singleton registrar instance. 64 | static WindowClassRegistrar* GetInstance() { 65 | if (!instance_) { 66 | instance_ = new WindowClassRegistrar(); 67 | } 68 | return instance_; 69 | } 70 | 71 | // Returns the name of the window class, registering the class if it hasn't 72 | // previously been registered. 73 | const wchar_t* GetWindowClass(); 74 | 75 | // Unregisters the window class. Should only be called if there are no 76 | // instances of the window. 77 | void UnregisterWindowClass(); 78 | 79 | private: 80 | WindowClassRegistrar() = default; 81 | 82 | static WindowClassRegistrar* instance_; 83 | 84 | bool class_registered_ = false; 85 | }; 86 | 87 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; 88 | 89 | const wchar_t* WindowClassRegistrar::GetWindowClass() { 90 | if (!class_registered_) { 91 | WNDCLASS window_class{}; 92 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); 93 | window_class.lpszClassName = kWindowClassName; 94 | window_class.style = CS_HREDRAW | CS_VREDRAW; 95 | window_class.cbClsExtra = 0; 96 | window_class.cbWndExtra = 0; 97 | window_class.hInstance = GetModuleHandle(nullptr); 98 | window_class.hIcon = 99 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); 100 | window_class.hbrBackground = 0; 101 | window_class.lpszMenuName = nullptr; 102 | window_class.lpfnWndProc = Win32Window::WndProc; 103 | RegisterClass(&window_class); 104 | class_registered_ = true; 105 | } 106 | return kWindowClassName; 107 | } 108 | 109 | void WindowClassRegistrar::UnregisterWindowClass() { 110 | UnregisterClass(kWindowClassName, nullptr); 111 | class_registered_ = false; 112 | } 113 | 114 | Win32Window::Win32Window() { 115 | ++g_active_window_count; 116 | } 117 | 118 | Win32Window::~Win32Window() { 119 | --g_active_window_count; 120 | Destroy(); 121 | } 122 | 123 | bool Win32Window::Create(const std::wstring& title, 124 | const Point& origin, 125 | const Size& size) { 126 | Destroy(); 127 | 128 | const wchar_t* window_class = 129 | WindowClassRegistrar::GetInstance()->GetWindowClass(); 130 | 131 | const POINT target_point = {static_cast(origin.x), 132 | static_cast(origin.y)}; 133 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); 134 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); 135 | double scale_factor = dpi / 96.0; 136 | 137 | HWND window = CreateWindow( 138 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW, 139 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), 140 | Scale(size.width, scale_factor), Scale(size.height, scale_factor), 141 | nullptr, nullptr, GetModuleHandle(nullptr), this); 142 | 143 | if (!window) { 144 | return false; 145 | } 146 | 147 | UpdateTheme(window); 148 | 149 | return OnCreate(); 150 | } 151 | 152 | bool Win32Window::Show() { 153 | return ShowWindow(window_handle_, SW_SHOWNORMAL); 154 | } 155 | 156 | // static 157 | LRESULT CALLBACK Win32Window::WndProc(HWND const window, 158 | UINT const message, 159 | WPARAM const wparam, 160 | LPARAM const lparam) noexcept { 161 | if (message == WM_NCCREATE) { 162 | auto window_struct = reinterpret_cast(lparam); 163 | SetWindowLongPtr(window, GWLP_USERDATA, 164 | reinterpret_cast(window_struct->lpCreateParams)); 165 | 166 | auto that = static_cast(window_struct->lpCreateParams); 167 | EnableFullDpiSupportIfAvailable(window); 168 | that->window_handle_ = window; 169 | } else if (Win32Window* that = GetThisFromHandle(window)) { 170 | return that->MessageHandler(window, message, wparam, lparam); 171 | } 172 | 173 | return DefWindowProc(window, message, wparam, lparam); 174 | } 175 | 176 | LRESULT 177 | Win32Window::MessageHandler(HWND hwnd, 178 | UINT const message, 179 | WPARAM const wparam, 180 | LPARAM const lparam) noexcept { 181 | switch (message) { 182 | case WM_DESTROY: 183 | window_handle_ = nullptr; 184 | Destroy(); 185 | if (quit_on_close_) { 186 | PostQuitMessage(0); 187 | } 188 | return 0; 189 | 190 | case WM_DPICHANGED: { 191 | auto newRectSize = reinterpret_cast(lparam); 192 | LONG newWidth = newRectSize->right - newRectSize->left; 193 | LONG newHeight = newRectSize->bottom - newRectSize->top; 194 | 195 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, 196 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE); 197 | 198 | return 0; 199 | } 200 | case WM_SIZE: { 201 | RECT rect = GetClientArea(); 202 | if (child_content_ != nullptr) { 203 | // Size and position the child window. 204 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, 205 | rect.bottom - rect.top, TRUE); 206 | } 207 | return 0; 208 | } 209 | 210 | case WM_ACTIVATE: 211 | if (child_content_ != nullptr) { 212 | SetFocus(child_content_); 213 | } 214 | return 0; 215 | 216 | case WM_DWMCOLORIZATIONCOLORCHANGED: 217 | UpdateTheme(hwnd); 218 | return 0; 219 | } 220 | 221 | return DefWindowProc(window_handle_, message, wparam, lparam); 222 | } 223 | 224 | void Win32Window::Destroy() { 225 | OnDestroy(); 226 | 227 | if (window_handle_) { 228 | DestroyWindow(window_handle_); 229 | window_handle_ = nullptr; 230 | } 231 | if (g_active_window_count == 0) { 232 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); 233 | } 234 | } 235 | 236 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { 237 | return reinterpret_cast( 238 | GetWindowLongPtr(window, GWLP_USERDATA)); 239 | } 240 | 241 | void Win32Window::SetChildContent(HWND content) { 242 | child_content_ = content; 243 | SetParent(content, window_handle_); 244 | RECT frame = GetClientArea(); 245 | 246 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left, 247 | frame.bottom - frame.top, true); 248 | 249 | SetFocus(child_content_); 250 | } 251 | 252 | RECT Win32Window::GetClientArea() { 253 | RECT frame; 254 | GetClientRect(window_handle_, &frame); 255 | return frame; 256 | } 257 | 258 | HWND Win32Window::GetHandle() { 259 | return window_handle_; 260 | } 261 | 262 | void Win32Window::SetQuitOnClose(bool quit_on_close) { 263 | quit_on_close_ = quit_on_close; 264 | } 265 | 266 | bool Win32Window::OnCreate() { 267 | // No-op; provided for subclasses. 268 | return true; 269 | } 270 | 271 | void Win32Window::OnDestroy() { 272 | // No-op; provided for subclasses. 273 | } 274 | 275 | void Win32Window::UpdateTheme(HWND const window) { 276 | DWORD light_mode; 277 | DWORD light_mode_size = sizeof(light_mode); 278 | LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, 279 | kGetPreferredBrightnessRegValue, 280 | RRF_RT_REG_DWORD, nullptr, &light_mode, 281 | &light_mode_size); 282 | 283 | if (result == ERROR_SUCCESS) { 284 | BOOL enable_dark_mode = light_mode == 0; 285 | DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, 286 | &enable_dark_mode, sizeof(enable_dark_mode)); 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:drawerbehavior_example/pages/drawer_3d.dart'; 4 | import 'package:drawerbehavior_example/pages/drawer_custom_item.dart'; 5 | import 'package:drawerbehavior_example/pages/drawer_custom_item_by_count.dart'; 6 | import 'package:drawerbehavior_example/pages/drawer_scale.dart'; 7 | import 'package:drawerbehavior_example/pages/drawer_scale_gradient.dart'; 8 | import 'package:drawerbehavior_example/pages/drawer_scale_icon.dart'; 9 | import 'package:drawerbehavior_example/pages/drawer_scale_left_3d_right_slide_.dart'; 10 | import 'package:drawerbehavior_example/pages/drawer_scale_left_right.dart'; 11 | import 'package:drawerbehavior_example/pages/drawer_scale_left_right_inverse.dart'; 12 | import 'package:drawerbehavior_example/pages/drawer_scale_no_animation.dart'; 13 | import 'package:drawerbehavior_example/pages/drawer_scale_peek_left.dart'; 14 | import 'package:drawerbehavior_example/pages/drawer_scale_peek_right.dart'; 15 | import 'package:drawerbehavior_example/pages/drawer_scale_right.dart'; 16 | import 'package:drawerbehavior_example/pages/drawer_slide.dart'; 17 | import 'package:drawerbehavior_example/pages/drawer_slide_custom_appbar.dart'; 18 | import 'package:drawerbehavior_example/pages/drawer_slide_menu_slide.dart'; 19 | import 'package:drawerbehavior_example/pages/drawer_slide_with_footer.dart'; 20 | import 'package:drawerbehavior_example/pages/drawer_slide_with_header.dart'; 21 | import 'package:drawerbehavior_example/pages/drawer_with_child.dart'; 22 | import 'package:flutter/material.dart'; 23 | 24 | void main() => runApp(MyApp()); 25 | 26 | class MyApp extends StatefulWidget { 27 | const MyApp({Key? key}) : super(key: key); 28 | 29 | @override 30 | State createState() => _MyAppState(); 31 | } 32 | 33 | class _MyAppState extends State { 34 | Widget createButton(context, {text, navigate, Color? color}) { 35 | Color buttonColor = color ?? Theme.of(context).primaryColor; 36 | return Container( 37 | margin: EdgeInsets.fromLTRB(12, 0, 12, 12), 38 | child: SizedBox( 39 | width: min(240, MediaQuery.of(context).size.width - 48), 40 | child: ElevatedButton( 41 | style: ElevatedButton.styleFrom(backgroundColor: buttonColor) 42 | .copyWith( 43 | foregroundColor: WidgetStateProperty.all( 44 | ThemeData.estimateBrightnessForColor(buttonColor) == 45 | Brightness.light 46 | ? Colors.black 47 | : Colors.white)), 48 | onPressed: () { 49 | Navigator.pushNamed(context, navigate); 50 | }, 51 | child: Text( 52 | text, 53 | textAlign: TextAlign.center, 54 | ))), 55 | ); 56 | } 57 | 58 | Widget home(context) { 59 | return Scaffold( 60 | appBar: AppBar( 61 | title: Text("Drawer Behavior"), 62 | ), 63 | body: SingleChildScrollView( 64 | child: Container( 65 | padding: EdgeInsets.all(16.0), 66 | child: Wrap( 67 | alignment: WrapAlignment.center, 68 | children: [ 69 | createButton(context, 70 | text: "Scale", 71 | navigate: "/scale", 72 | color: Theme.of(context).colorScheme.secondary), 73 | createButton(context, 74 | text: "Scale - with Icon", 75 | navigate: "/slide/scaleicon", 76 | color: Theme.of(context).colorScheme.secondary), 77 | createButton(context, 78 | text: "Scale - no animation", 79 | navigate: "/scale/noanimation", 80 | color: Theme.of(context).colorScheme.secondary), 81 | createButton(context, 82 | text: "Scale - Gradient Background", 83 | navigate: "/scale/background/gradient", 84 | color: Theme.of(context).colorScheme.secondary), 85 | createButton(context, 86 | text: "3D", 87 | navigate: "/3d", 88 | color: Theme.of(context).colorScheme.secondary), 89 | Divider(height: 16, color: Theme.of(context).dividerColor), 90 | Text("Align Top"), 91 | Divider(height: 16, color: Theme.of(context).dividerColor), 92 | createButton(context, 93 | text: "Slide ", 94 | navigate: "/slide", 95 | color: Theme.of(context).colorScheme.secondary), 96 | createButton(context, 97 | text: "Slide - Menu Slide ", 98 | navigate: "/slide/menuslide", 99 | color: Theme.of(context).colorScheme.secondary), 100 | createButton(context, 101 | text: "Slide - with Header View", 102 | navigate: "/slide/header", 103 | color: Theme.of(context).colorScheme.secondary), 104 | createButton(context, 105 | text: "Slide - with Footer View", 106 | navigate: "/drawer8", 107 | color: Theme.of(context).colorScheme.secondary), 108 | Divider(height: 16, color: Theme.of(context).dividerColor), 109 | Text("Duo Drawer"), 110 | Divider(height: 16, color: Theme.of(context).dividerColor), 111 | createButton(context, 112 | text: "Left & Right", 113 | navigate: "/duo/leftandright", 114 | color: Theme.of(context).colorScheme.secondary), 115 | createButton(context, 116 | text: "Left & Right (Inverse)", 117 | navigate: "/duo/leftandright/inverse", 118 | color: Theme.of(context).colorScheme.secondary), 119 | createButton(context, 120 | text: "Left(3D) & Right(Slide)", 121 | navigate: "/duo/left3dandrightslide", 122 | color: Theme.of(context).colorScheme.secondary), 123 | createButton(context, 124 | text: "Right", 125 | navigate: "/duo/right", 126 | color: Theme.of(context).colorScheme.secondary), 127 | Divider(height: 16, color: Theme.of(context).dividerColor), 128 | Text("Peek"), 129 | Divider(height: 16, color: Theme.of(context).dividerColor), 130 | createButton(context, 131 | text: "Peek Left", 132 | navigate: "/peek/duo/left", 133 | color: Theme.of(context).colorScheme.secondary), 134 | createButton(context, 135 | text: "Peek Right", 136 | navigate: "/peek/duo/right", 137 | color: Theme.of(context).colorScheme.secondary), 138 | Divider(height: 16, color: Theme.of(context).dividerColor), 139 | Text("Customize"), 140 | Divider(height: 16, color: Theme.of(context).dividerColor), 141 | createButton(context, 142 | text: "Customize Item", 143 | navigate: "/custom/item", 144 | color: Theme.of(context).colorScheme.secondary), 145 | createButton(context, 146 | text: "Customize Item by Count", 147 | navigate: "/custom/item/count", 148 | color: Theme.of(context).colorScheme.secondary), 149 | createButton(context, 150 | text: "Custom AppBar", 151 | navigate: "/custom/appbar", 152 | color: Theme.of(context).colorScheme.secondary), 153 | createButton(context, 154 | text: "Using child", 155 | navigate: "/custom/withchild", 156 | color: Theme.of(context).colorScheme.secondary), 157 | ], 158 | )), 159 | ), 160 | ); 161 | } 162 | 163 | @override 164 | Widget build(BuildContext context) { 165 | final theme = ThemeData(primarySwatch: Colors.teal); 166 | return MaterialApp( 167 | theme: theme.copyWith( 168 | colorScheme: 169 | theme.colorScheme.copyWith(secondary: Colors.amberAccent)), 170 | routes: { 171 | "/": home, 172 | "/scale": (context) => createPage(DrawerScale()), 173 | "/scale/noanimation": (context) => createPage(DrawerScaleNoAnimation()), 174 | "/scale/background/gradient": (context) => 175 | createPage(DrawerScaleGradient()), 176 | "/slide": (context) => createPage(DrawerSlide()), 177 | "/slide/menuslide": (context) => createPage(DrawerSlideMenuSlide()), 178 | "/slide/header": (context) => createPage(DrawerSlideWithHeader()), 179 | "/slide/scaleicon": (context) => createPage(DrawerScaleIcon()), 180 | "/duo/leftandright": (context) => createPage(DrawerLeftAndRight()), 181 | "/duo/right": (context) => createPage(DrawerRight()), 182 | "/duo/leftandright/inverse": (context) => 183 | createPage(DrawerLeftAndRightInverse()), 184 | "/3d": (context) => createPage(Drawer3d()), 185 | "/duo/left3dandrightslide": (context) => 186 | createPage(DrawerLeft3DAndRightSlide()), 187 | "/drawer8": (context) => createPage(DrawerSlideWithFooter()), 188 | "/peek/duo/left": (context) => createPage(DrawerPeekLeft()), 189 | "/peek/duo/right": (context) => createPage(DrawerPeekRight()), 190 | "/custom/appbar": (context) => createPage(DrawerSlideCustomAppBar()), 191 | "/custom/item": (context) => createPage(DrawerCustomItem()), 192 | "/custom/item/count": (context) => 193 | createPage(DrawerCustomItemByCount()), 194 | "/custom/withchild": (context) => createPage(DrawerWithChild()), 195 | }, 196 | ); 197 | } 198 | 199 | Widget createPage(Widget child) { 200 | return Scaffold( 201 | appBar: AppBar(), 202 | body: child, 203 | ); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/drawerbehavior.svg)](https://pub.dartlang.org/packages/drawerbehavior) 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-4-orange.svg?style=flat-square)](#contributors-) 4 | 5 | 6 | # Drawer Behavior - Flutter 7 | 8 | **Drawer Behavior** is a Flutter library that provides advanced effects and behaviors for the side navigation drawer. Unlike the standard Flutter drawer, this package allows you to create immersive interactions such as moving the view, scaling the view's height, or adding 3D effects while the drawer slides. 9 | 10 | ![Alt Text](https://github.com/shiburagi/Drawer-Behavior-Flutter/blob/preview/preview-ios-gif.gif) 11 | 12 | ## ✨ Features 13 | 14 | * **Scale Effect:** smoothly scales down the main content as the drawer opens. 15 | 16 | * **3D Effect:** Adds a rotation depth effect to the main content. 17 | 18 | * **Multi-Directional:** Supports both Left and Right side drawers. 19 | 20 | * **Peek Drawer:** Keep a portion of the drawer visible even when closed. 21 | 22 | * **Customization:** Full control over headers, footers, item builders, and animations. 23 | 24 | * **Null-Safety:** Fully supports Dart null-safety. 25 | 26 | ## 📦 Installation 27 | 28 | Add this to your package's `pubspec.yaml` file: 29 | 30 | ```yaml 31 | dependencies: 32 | drawerbehavior: ^3.0.0 # Check pub.dev for the latest version 33 | ``` 34 | 35 | Install it via command line: 36 | 37 | ```yaml 38 | flutter pub get 39 | ``` 40 | 41 | ## 🚀 Usage 42 | 43 | ### 1. Import the package 44 | 45 | ```dart 46 | import 'package:drawerbehavior/drawerbehavior.dart'; 47 | ``` 48 | 49 | ### 2. Basic Implementation 50 | 51 | Replace your standard `Scaffold` with `DrawerScaffold`. Define your `drawers` using `SideDrawer` and your main content using the `builder`. 52 | 53 | ```dart 54 | import 'package:flutter/material.dart'; 55 | import 'package:drawerbehavior/drawerbehavior.dart'; 56 | 57 | class MyHomePage extends StatefulWidget { 58 | @override 59 | _MyHomePageState createState() => _MyHomePageState(); 60 | } 61 | 62 | class _MyHomePageState extends State { 63 | int selectedMenuItemId = 0; 64 | 65 | // Define your menu items 66 | final Menu menu = Menu( 67 | items: [ 68 | MenuItem(id: 0, title: 'Home', icon: Icons.home), 69 | MenuItem(id: 1, title: 'Profile', icon: Icons.person), 70 | MenuItem(id: 2, title: 'Settings', icon: Icons.settings), 71 | ], 72 | ); 73 | 74 | @override 75 | Widget build(BuildContext context) { 76 | return DrawerScaffold( 77 | // App Bar handles the menu button automatically 78 | appBar: AppBar( 79 | title: Text("Drawer Behavior"), 80 | ), 81 | 82 | // Define the drawer(s) 83 | drawers: [ 84 | SideDrawer( 85 | percentage: 0.6, // Scale the main view down to 60% 86 | menu: menu, 87 | direction: Direction.left, 88 | animation: true, 89 | color: Theme.of(context).primaryColor, 90 | selectedItemId: selectedMenuItemId, 91 | onMenuItemSelected: (itemId) { 92 | setState(() { 93 | selectedMenuItemId = itemId; 94 | }); 95 | }, 96 | ) 97 | ], 98 | 99 | // Build the main screen content based on selection 100 | builder: (context, id) => IndexedStack( 101 | index: selectedMenuItemId, 102 | children: [ 103 | Center(child: Text("Home Page")), 104 | Center(child: Text("Profile Page")), 105 | Center(child: Text("Settings Page")), 106 | ], 107 | ), 108 | ); 109 | } 110 | } 111 | 112 | ``` 113 | 114 | ## 🎨 Customization 115 | 116 | You can fine-tune the look and feel using parameters in `DrawerScaffold` and `SideDrawer`. 117 | 118 | ### DrawerScaffold Options 119 | 120 | | Parameter | Description | 121 | | ----- | ----- | 122 | | `drawers` | A list of `SideDrawer` widgets (e.g., left and right). | 123 | | `builder` | Builder for the main content area. Use this to react to state changes. | 124 | | `defaultDirection` | The default direction (left/right) controlled by the toggle button. | 125 | | `cornerRadius` | Radius of the main content's corners when the drawer is open. | 126 | | `contentShadow` | Shadow definition for the main content panel. | 127 | | `enableGestures` | Boolean to enable/disable drag gestures. | 128 | | `onSlide` | Callback triggered while the drawer is sliding. | 129 | | `controller` | `DrawerScaffoldController` for programmatic control (open/close). | 130 | 131 | ### SideDrawer Options 132 | 133 | | Parameter | Description | 134 | | ----- | ----- | 135 | | `percentage` | How much the main content scales down (e.g., 0.8) when open. | 136 | | `degree` | The rotation degree for the **3D effect** (between 15 and 45). | 137 | | `slide` | If `true`, the main content slides horizontally with the drawer. | 138 | | `peekMenu` | If `true`, a small part of the drawer remains visible when closed. | 139 | | `peekSize` | The width of the drawer when `peekMenu` is active. | 140 | | `direction` | `Direction.left` or `Direction.right`. | 141 | | `headerView` | Widget to display at the top of the drawer. | 142 | | `footerView` | Widget to display at the bottom of the drawer. | 143 | | `itemBuilder` | Custom builder for menu items if you don't want the default look. | 144 | | `color` | Background color of the drawer. | 145 | | `background` | Background `DecorationImage` for the drawer. | 146 | 147 | ## 🔄 Migration Guide 148 | 149 | If you are upgrading from older versions, please note the following breaking changes: 150 | 151 | ### v2.0 to v3.0 (Null-safety & API Cleanup) 152 | 153 | 1. **DrawerScaffold:** 154 | 155 | * `mainDrawer` property is now **`defaultDirection`**. 156 | 157 | * `percentage` property moved inside `SideDrawer`. 158 | 159 | * `contentView` is now **`builder`**. 160 | 161 | 2. **SideDrawer:** 162 | 163 | * `menuView` is now replaced by the `drawers` list containing `SideDrawer`. 164 | 165 | **Example:** 166 | 167 | ```dart 168 | // OLD 169 | DrawerScaffold( 170 | mainDrawer: Direction.left, 171 | contentView: Screen(...), 172 | percentage: 0.6, 173 | menuView: MenuView(...), 174 | ) 175 | 176 | // NEW 177 | DrawerScaffold( 178 | defaultDirection: Direction.left, 179 | builder: (context, id) => ..., 180 | drawers: [ 181 | SideDrawer( 182 | percentage: 0.6, 183 | ... 184 | ) 185 | ], 186 | ) 187 | 188 | ``` 189 | 190 | ## 📱 Previews 191 | 192 | ### Scale Effect 193 | 194 | 195 | 196 | ```dart 197 | DrawerScaffold( 198 | drawers: [ 199 | SideDrawer( 200 | percentage: 0.6, 201 | // ... 202 | ) 203 | ], 204 | // ... 205 | ); 206 | 207 | ``` 208 | 209 | ### Right Drawer 210 | 211 | 212 | 213 | ```dart 214 | DrawerScaffold( 215 | drawers: [ 216 | SideDrawer( 217 | direction: Direction.right, 218 | // ... 219 | ) 220 | ], 221 | // ... 222 | ); 223 | 224 | ``` 225 | 226 | ### 3D Effect 227 | 228 | 229 | 230 | ```dart 231 | DrawerScaffold( 232 | drawers: [ 233 | SideDrawer( 234 | degree: 45, 235 | // ... 236 | ) 237 | ], 238 | // ... 239 | ); 240 | 241 | ``` 242 | 243 | ### Drawer with Header 244 | 245 | 246 | ```dart 247 | DrawerScaffold( 248 | headerView: headerView(context), 249 | // ... 250 | ); 251 | 252 | ``` 253 | 254 | ### Drawer with Footer 255 | 256 | 257 | 258 | ```dart 259 | DrawerScaffold( 260 | footerView: footerView(context), 261 | // ... 262 | ); 263 | 264 | ``` 265 | 266 | ### Drawer with Header and Custom Builder 267 | 268 | 269 | 270 | ```dart 271 | DrawerScaffold( 272 | headerView: headerView(context), 273 | drawers: [ 274 | SideDrawer( 275 | itemBuilder: (BuildContext context, MenuItem menuItem, bool isSelected) { 276 | return Container( 277 | color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(0.7) : Colors.transparent, 278 | padding: EdgeInsets.fromLTRB(24, 16, 24, 16), 279 | child: Text( 280 | menuItem.title, 281 | style: Theme.of(context).textTheme.subtitle1?.copyWith( 282 | color: isSelected ? Colors.black87 : Colors.white70), 283 | ), 284 | ); 285 | } 286 | ) 287 | ], 288 | // ... 289 | ); 290 | 291 | ``` 292 | 293 | ### Peek Drawer 294 | 295 | 296 | 297 | ```dart 298 | DrawerScaffold( 299 | headerView: headerView(context), 300 | drawers: [ 301 | SideDrawer( 302 | peekMenu: true, 303 | percentage: 1, 304 | menu: menuWithIcon, 305 | direction: Direction.left, 306 | ) 307 | ], 308 | // ... 309 | ); 310 | 311 | ``` 312 | 313 | ## 🤝 Contributing 314 | 315 | Contributions are welcome! Please feel free to submit a Pull Request. 316 | 317 | ## 📄 License 318 | 319 | This project is licensed under the MIT License - see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details. 320 | 321 | *Based on the original work by [shiburagi](https://github.com/shiburagi).* 322 | 323 | 324 | ## Contributors 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 |
trademunch
trademunch

💻
anjarnaufals
anjarnaufals

💻
Vladimir Vlach
Vladimir Vlach

💻
Chris Hayen
Chris Hayen

💻
339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | --------------------------------------------------------------------------------