├── CODEOWNERS ├── example ├── linux │ ├── .gitignore │ ├── main.cc │ ├── flutter │ │ ├── generated_plugin_registrant.cc │ │ ├── generated_plugin_registrant.h │ │ ├── generated_plugins.cmake │ │ └── CMakeLists.txt │ ├── my_application.h │ ├── my_application.cc │ └── CMakeLists.txt ├── web │ ├── favicon.png │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ ├── manifest.json │ └── index.html ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── liugl │ │ │ │ │ │ └── flutter_switch_clipper_example │ │ │ │ │ │ └── MainActivity.java │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── settings.gradle │ └── build.gradle ├── macos │ ├── 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 │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ └── Podfile ├── ios │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── AppDelegate.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 │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── 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 │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── .gitignore │ └── Podfile ├── windows │ ├── runner │ │ ├── resources │ │ │ └── app_icon.ico │ │ ├── resource.h │ │ ├── CMakeLists.txt │ │ ├── utils.h │ │ ├── runner.exe.manifest │ │ ├── flutter_window.h │ │ ├── main.cpp │ │ ├── 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 ├── .metadata ├── README.md ├── .gitignore ├── pubspec.yaml ├── lib │ └── main.dart ├── pubspec.lock └── analysis_options.yaml ├── preview ├── cs.gif ├── cs2.gif ├── cs3.gif ├── cs4.gif ├── cs5.gif ├── fc.gif └── fv.gif ├── lib ├── src │ ├── helper │ │ ├── clipper_enum.dart │ │ └── matrix4_transform.dart │ ├── clippers │ │ ├── animation_clipper.dart │ │ ├── circle_clipper.dart │ │ ├── shutter_clipper.dart │ │ ├── wave_clipper.dart │ │ ├── camera_clipper.dart │ │ └── fill_clipper.dart │ └── switch_clipper.dart └── flutter_switch_clipper.dart ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── .gitignore ├── pubspec.yaml ├── README.md ├── pubspec.lock └── analysis_options.yaml /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @xSILENCEx 2 | -------------------------------------------------------------------------------- /example/linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /preview/cs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/cs.gif -------------------------------------------------------------------------------- /preview/cs2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/cs2.gif -------------------------------------------------------------------------------- /preview/cs3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/cs3.gif -------------------------------------------------------------------------------- /preview/cs4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/cs4.gif -------------------------------------------------------------------------------- /preview/cs5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/cs5.gif -------------------------------------------------------------------------------- /preview/fc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/fc.gif -------------------------------------------------------------------------------- /preview/fv.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/preview/fv.gif -------------------------------------------------------------------------------- /example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/example/web/favicon.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /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/fluttercandies/flutter_switch_clipper/HEAD/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/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/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /lib/src/helper/clipper_enum.dart: -------------------------------------------------------------------------------- 1 | /// 填充方向 2 | enum FillAlignment { left, top, right, bottom } 3 | 4 | /// 波浪方向 5 | enum WaveAlignment { left, right } 6 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/HEAD/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /lib/src/clippers/animation_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | abstract class AnimationClip { 4 | const AnimationClip(); 5 | 6 | Path getClip(Size size, Animation animation); 7 | } 8 | -------------------------------------------------------------------------------- /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/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fluttercandies/flutter_switch_clipper/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/fluttercandies/flutter_switch_clipper/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /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/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /example/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/app/src/main/java/com/liugl/flutter_switch_clipper_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.liugl.flutter_switch_clipper_example; 2 | 3 | import io.flutter.embedding.android.FlutterActivity; 4 | 5 | public class MainActivity extends FlutterActivity { 6 | } 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /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/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/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/flutter_switch_clipper.dart: -------------------------------------------------------------------------------- 1 | export 'src/clippers/camera_clipper.dart'; 2 | export 'src/clippers/circle_clipper.dart'; 3 | export 'src/clippers/fill_clipper.dart'; 4 | export 'src/clippers/shutter_clipper.dart'; 5 | export 'src/clippers/wave_clipper.dart'; 6 | export 'src/helper/clipper_enum.dart'; 7 | export 'src/switch_clipper.dart'; 8 | -------------------------------------------------------------------------------- /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: 18116933e77adc82f80866c928266a5b4f1ed645 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /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: 18116933e77adc82f80866c928266a5b4f1ed645 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/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/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.7 2 | * Update README.md 3 | * Fix typos 4 | 5 | ## 0.0.6 6 | 7 | * Optimize clipper objects 8 | * Update demo URL 9 | 10 | ## 0.0.5 11 | 12 | * Adapt flutter sdk 13 | 14 | ## 0.0.4 15 | 16 | * Add two clippers, fix bug 17 | 18 | ## 0.0.3 19 | 20 | * Redesign the architecture, add optional parameters 21 | 22 | ## 0.0.2 23 | 24 | * Complete introduction and example 25 | 26 | ## 0.0.1 27 | 28 | * First commit 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /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/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | #import "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /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/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /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/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:4.1.0' 9 | } 10 | } 11 | 12 | allprojects { 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | } 18 | 19 | rootProject.buildDir = '../build' 20 | subprojects { 21 | project.buildDir = "${rootProject.buildDir}/${project.name}" 22 | project.evaluationDependsOn(':app') 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /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/README.md: -------------------------------------------------------------------------------- 1 | # flutter_switch_clipper_example 2 | 3 | Demonstrates how to use the flutter_switch_clipper 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.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(runner LANGUAGES CXX) 3 | 4 | add_executable(${BINARY_NAME} WIN32 5 | "flutter_window.cpp" 6 | "main.cpp" 7 | "utils.cpp" 8 | "win32_window.cpp" 9 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 10 | "Runner.rc" 11 | "runner.exe.manifest" 12 | ) 13 | apply_standard_settings(${BINARY_NAME}) 14 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 15 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 16 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 17 | add_dependencies(${BINARY_NAME} flutter_assemble) 18 | -------------------------------------------------------------------------------- /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 = flutter_switch_clipper_example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.liugl.flutterSwitchClipperExample 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2021 com.liugl. 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/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/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/src/clippers/circle_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'animation_clipper.dart'; 6 | 7 | /// CircleClipper 8 | class CircleClipper extends AnimationClip { 9 | CircleClipper(); 10 | 11 | /// Size备份 12 | Size? _size; 13 | 14 | /// 对角线长度 15 | late double _diagonal; 16 | 17 | @override 18 | Path getClip(Size size, Animation animation) { 19 | return Path() 20 | ..addOval( 21 | Rect.fromCircle( 22 | center: Offset(size.width / 2, size.height / 2), 23 | radius: _getDiagonal(size) / 2 * animation.value, 24 | ), 25 | ); 26 | } 27 | 28 | /// 计算对角线 29 | double _getDiagonal(Size size) { 30 | if (size != _size) { 31 | _size = size; 32 | _diagonal = math.sqrt(size.width * size.width + size.height * size.height); 33 | } 34 | 35 | return _diagonal; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 xSILENCEx 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "flutter_switch_clipper_example", 3 | "short_name": "flutter_switch_clipper_example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "Demonstrates how to use the flutter_switch_clipper plugin.", 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 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /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/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 32 | end 33 | 34 | post_install do |installer| 35 | installer.pods_project.targets.each do |target| 36 | flutter_additional_ios_build_settings(target) 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /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.CreateAndShow(L"flutter_switch_clipper_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 | -------------------------------------------------------------------------------- /example/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.14' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | end 35 | 36 | post_install do |installer| 37 | installer.pods_project.targets.each do |target| 38 | flutter_additional_macos_build_settings(target) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /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/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_switch_clipper_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/ephemeral 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_switch_clipper 2 | description: A Flutter package that two widgets switch with default clipper or customized clipper. 3 | version: 0.0.7 4 | homepage: https://github.com/fluttercandies/flutter_switch_clipper 5 | 6 | environment: 7 | sdk: ">=2.12.0 <4.0.0" 8 | flutter: ">=1.17.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | flutter_lints: ^1.0.0 18 | 19 | # For information on the generic Dart part of this file, see the 20 | # following page: https://dart.dev/tools/pub/pubspec 21 | 22 | # The following section is specific to Flutter. 23 | flutter: 24 | 25 | # To add assets to your package, add an assets section, like this: 26 | # assets: 27 | # - images/a_dot_burr.jpeg 28 | # - images/a_dot_ham.jpeg 29 | # 30 | # For details regarding assets in packages, see 31 | # https://flutter.dev/assets-and-images/#from-packages 32 | # 33 | # An image asset can refer to one or more resolution-specific "variants", see 34 | # https://flutter.dev/assets-and-images/#resolution-aware. 35 | 36 | # To add custom fonts to your package, add a fonts section here, 37 | # in this "flutter" section. Each entry in this list should have a 38 | # "family" key with the font family name, and a "fonts" key with a 39 | # list giving the asset and other descriptors for the font. For 40 | # example: 41 | # fonts: 42 | # - family: Schyler 43 | # fonts: 44 | # - asset: fonts/Schyler-Regular.ttf 45 | # - asset: fonts/Schyler-Italic.ttf 46 | # style: italic 47 | # - family: Trajan Pro 48 | # fonts: 49 | # - asset: fonts/TrajanPro.ttf 50 | # - asset: fonts/TrajanPro_Bold.ttf 51 | # weight: 700 52 | # 53 | # For details regarding fonts in packages, see 54 | # https://flutter.dev/custom-fonts/#from-packages 55 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 | 27 | android { 28 | compileSdkVersion 30 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.liugl.flutter_switch_clipper_example" 38 | minSdkVersion 16 39 | targetSdkVersion 30 40 | versionCode flutterVersionCode.toInteger() 41 | versionName flutterVersionName 42 | } 43 | 44 | buildTypes { 45 | release { 46 | // TODO: Add your own signing config for the release build. 47 | // Signing with the debug keys for now, so `flutter run --release` works. 48 | signingConfig signingConfigs.debug 49 | } 50 | } 51 | } 52 | 53 | flutter { 54 | source '../..' 55 | } 56 | -------------------------------------------------------------------------------- /lib/src/clippers/shutter_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helper/clipper_enum.dart'; 3 | 4 | import 'animation_clipper.dart'; 5 | 6 | /// ShutterClipper 7 | class ShutterClipper extends AnimationClip { 8 | ShutterClipper({ 9 | this.activeAlignment = FillAlignment.top, 10 | this.fragment = 6, 11 | }); 12 | 13 | /// 朝向 14 | final FillAlignment activeAlignment; 15 | 16 | /// 叶片数量 17 | final int fragment; 18 | 19 | @override 20 | Path getClip(Size size, Animation animation) { 21 | //叶片尺寸 22 | final double fragmentSize = _handleFragmentSize(size); 23 | 24 | final Path path = Path(); 25 | 26 | for (int i = 0; i < fragment; i++) { 27 | double left = 0; 28 | double top = fragmentSize * i; 29 | double width = size.width; 30 | double height = fragmentSize * animation.value; 31 | 32 | if (activeAlignment == FillAlignment.left) { 33 | left = fragmentSize * i; 34 | top = 0; 35 | width = fragmentSize * animation.value; 36 | height = size.height; 37 | } else if (activeAlignment == FillAlignment.bottom) { 38 | left = 0; 39 | top = fragmentSize * (i + 1 - animation.value); 40 | width = size.width; 41 | height = fragmentSize * animation.value; 42 | } else if (activeAlignment == FillAlignment.right) { 43 | left = fragmentSize * (i + 1 - animation.value); 44 | top = 0; 45 | width = fragmentSize * animation.value; 46 | height = size.height; 47 | } 48 | 49 | path.addRect(Rect.fromLTWH(left, top, width, height)); 50 | } 51 | 52 | return path; 53 | } 54 | 55 | /// 处理叶片尺寸 56 | double _handleFragmentSize(Size size) { 57 | if (activeAlignment == FillAlignment.top || activeAlignment == FillAlignment.bottom) { 58 | return size.height / fragment; 59 | } 60 | 61 | return size.width / fragment; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /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 | if (target_length == 0) { 52 | return std::string(); 53 | } 54 | std::string utf8_string; 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/clippers/wave_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helper/clipper_enum.dart'; 3 | 4 | import 'animation_clipper.dart'; 5 | 6 | /// WaveClipper 7 | /// 波浪裁剪 8 | class WaveClipper extends AnimationClip { 9 | WaveClipper({ 10 | this.waveHeight = 10, 11 | this.waveWidth = 100, 12 | this.waveSpeed = 2, 13 | this.waveAlignment = WaveAlignment.left, 14 | }); 15 | 16 | /// 波浪高度 17 | final double waveHeight; 18 | 19 | /// 波浪宽度 20 | final double waveWidth; 21 | 22 | /// 波浪速度 23 | final int waveSpeed; 24 | 25 | /// 波浪朝向(流动方向) 26 | final WaveAlignment waveAlignment; 27 | 28 | @override 29 | Path getClip(Size size, Animation animation) { 30 | final double w = size.width; 31 | final double h = size.height; 32 | final Path path = Path(); 33 | 34 | //每组波浪的数量 35 | final int everyGroupWaveCount = (w / waveWidth).ceil(); 36 | 37 | //波浪虚拟数量 38 | //2代表只准备两组循环利用 39 | final int waveCount = 2 * everyGroupWaveCount; 40 | 41 | path.moveTo(0, -waveHeight); 42 | for (int i = 0; i < waveCount; i++) { 43 | path.relativeQuadraticBezierTo(waveWidth / 2, -waveHeight * 2, waveWidth, 0); 44 | path.relativeQuadraticBezierTo(waveWidth / 2, waveHeight * 2, waveWidth, 0); 45 | } 46 | path.lineTo(waveWidth * waveCount * 2, h); 47 | path.lineTo(0, h); 48 | path.close(); 49 | 50 | //波浪总数量 51 | final int totalCount = waveSpeed * everyGroupWaveCount; 52 | 53 | if (waveAlignment == WaveAlignment.right) { 54 | //波浪往右 55 | //波浪总宽度 56 | final double waveTotalWidth = totalCount * waveWidth; 57 | return path.shift( 58 | Offset( 59 | -waveTotalWidth * (1 - animation.value), 60 | (h + waveHeight * 2) * (1 - animation.value), 61 | ), 62 | ); 63 | } 64 | 65 | return path.shift( 66 | Offset( 67 | -waveWidth * ((totalCount * animation.value) % 2), 68 | (h + waveHeight * 2) * (1 - animation.value), 69 | ), 70 | ); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /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 | return true; 30 | } 31 | 32 | void FlutterWindow::OnDestroy() { 33 | if (flutter_controller_) { 34 | flutter_controller_ = nullptr; 35 | } 36 | 37 | Win32Window::OnDestroy(); 38 | } 39 | 40 | LRESULT 41 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message, 42 | WPARAM const wparam, 43 | LPARAM const lparam) noexcept { 44 | // Give Flutter, including plugins, an opportunity to handle window messages. 45 | if (flutter_controller_) { 46 | std::optional result = 47 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, 48 | lparam); 49 | if (result) { 50 | return *result; 51 | } 52 | } 53 | 54 | switch (message) { 55 | case WM_FONTCHANGE: 56 | flutter_controller_->engine()->ReloadSystemFonts(); 57 | break; 58 | } 59 | 60 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam); 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/clippers/camera_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math' as math; 2 | 3 | import 'package:flutter/material.dart'; 4 | import '../helper/matrix4_transform.dart'; 5 | 6 | import 'animation_clipper.dart'; 7 | 8 | /// CameraClipper 9 | /// 快门裁剪 10 | class CameraClipper extends AnimationClip { 11 | CameraClipper({this.lensAperture = 20, this.lensAngle = -120}); 12 | 13 | /// 镜头孔径 14 | final double lensAperture; 15 | 16 | /// 镜头旋转角度 17 | final double lensAngle; 18 | 19 | /// Size备份 20 | Size? _size; 21 | 22 | /// 对角线长度 23 | late double _diagonal; 24 | 25 | @override 26 | Path getClip(Size size, Animation animation) { 27 | //基础数据 28 | final double w = size.width; 29 | final double h = size.height; 30 | final double r = _getDiagonal(size) / 2 + lensAperture; 31 | final Offset center = Offset(w / 2, h / 2); 32 | 33 | //准备叶片路径 34 | Path bladePath = Path(); 35 | 36 | //起始点 37 | final Offset start = center.translate(-math.sqrt(3) / 2 * lensAperture, lensAperture / 2); 38 | bladePath.moveTo(start.dx, start.dy); 39 | 40 | //顶点 41 | final double b = math.sqrt(r * r + r - lensAperture * lensAperture); 42 | bladePath.lineTo(start.dx, start.dy - b); 43 | 44 | //画弧 45 | final double endX = r * (math.sqrt(3) / 2) + center.dx; 46 | final double endY = -r / 2 + center.dy; 47 | bladePath.arcToPoint(Offset(endX, endY), radius: Radius.circular(r)); 48 | bladePath.close(); 49 | 50 | //平移 51 | bladePath = bladePath.shift(Offset(0, -r * (1 - animation.value))); 52 | 53 | //准备联合路径 54 | Path path = bladePath; 55 | 56 | //循环联合路径 57 | for (int i = 1; i <= 5; i++) { 58 | final Matrix4 rM = Matrix4Transform().rotateDegrees(i * 60, origin: center).matrix4; 59 | path = Path.combine(PathOperation.union, path, bladePath.transform(rM.storage)); 60 | } 61 | 62 | //镜头旋转 63 | final Matrix4 roate = 64 | Matrix4Transform().rotateDegrees(lensAngle * animation.value, origin: center).matrix4; 65 | return path.transform(roate.storage); 66 | } 67 | 68 | /// 计算对角线 69 | double _getDiagonal(Size size) { 70 | if (size != _size) { 71 | _size = size; 72 | _diagonal = math.sqrt(size.width * size.width + size.height * size.height); 73 | } 74 | 75 | return _diagonal; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /lib/src/clippers/fill_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../helper/clipper_enum.dart'; 3 | 4 | import 'animation_clipper.dart'; 5 | 6 | ///填充裁切 7 | class FillClipper extends AnimationClip { 8 | const FillClipper({ 9 | this.fillAlignment = FillAlignment.left, 10 | this.fillOffset = 20, 11 | }); 12 | 13 | /// * 裁切起始方向 14 | /// * 默认 `FillAlignment.left` 15 | final FillAlignment fillAlignment; 16 | 17 | /// * 裁切弧度偏移量 18 | /// * 默认`20` 19 | final double fillOffset; 20 | 21 | @override 22 | Path getClip(Size size, Animation animation) { 23 | final double w = size.width; 24 | final double h = size.height; 25 | 26 | final Path path = Path(); 27 | 28 | if (fillAlignment == FillAlignment.top) { 29 | path 30 | ..moveTo(0, -fillOffset) 31 | ..lineTo(w, -fillOffset) 32 | ..lineTo(w, h * animation.value - fillOffset * (1 - animation.value)) 33 | ..quadraticBezierTo( 34 | w / 2, h * animation.value, 0, h * animation.value - fillOffset * (1 - animation.value)) 35 | ..close(); 36 | } else if (fillAlignment == FillAlignment.right) { 37 | path 38 | ..moveTo(w + fillOffset, 0) 39 | ..lineTo(w + fillOffset, h) 40 | ..lineTo((w + fillOffset) * (1 - animation.value), h) 41 | ..quadraticBezierTo( 42 | (w - (fillOffset - 1)) * (1 - animation.value), 43 | h / 2, 44 | (w + fillOffset) * (1 - animation.value), 45 | 0, 46 | ) 47 | ..close(); 48 | } else if (fillAlignment == FillAlignment.bottom) { 49 | path 50 | ..moveTo(0, h + fillOffset) 51 | ..lineTo(w, h + fillOffset) 52 | ..lineTo(w, (h + fillOffset) * (1 - animation.value)) 53 | ..quadraticBezierTo(w / 2, (h - (fillOffset - 1)) * (1 - animation.value), 0, 54 | (h + fillOffset) * (1 - animation.value)) 55 | ..close(); 56 | } else { 57 | path 58 | ..moveTo(-fillOffset, 0) 59 | ..lineTo(-fillOffset, h) 60 | ..lineTo(w * animation.value - fillOffset * (1 - animation.value), h) 61 | ..quadraticBezierTo( 62 | (w + fillOffset - 1) * animation.value, 63 | h / 2, 64 | w * animation.value - fillOffset * (1 - animation.value), 65 | 0, 66 | ) 67 | ..close(); 68 | } 69 | 70 | return path; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/linux/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | 11 | # Serves the same purpose as list(TRANSFORM ... PREPEND ...), 12 | # which isn't available in 3.10. 13 | function(list_prepend LIST_NAME PREFIX) 14 | set(NEW_LIST "") 15 | foreach(element ${${LIST_NAME}}) 16 | list(APPEND NEW_LIST "${PREFIX}${element}") 17 | endforeach(element) 18 | set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) 19 | endfunction() 20 | 21 | # === Flutter Library === 22 | # System-level dependencies. 23 | find_package(PkgConfig REQUIRED) 24 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 25 | pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) 26 | pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) 27 | 28 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") 29 | 30 | # Published to parent scope for install step. 31 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 32 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 33 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 34 | set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) 35 | 36 | list(APPEND FLUTTER_LIBRARY_HEADERS 37 | "fl_basic_message_channel.h" 38 | "fl_binary_codec.h" 39 | "fl_binary_messenger.h" 40 | "fl_dart_project.h" 41 | "fl_engine.h" 42 | "fl_json_message_codec.h" 43 | "fl_json_method_codec.h" 44 | "fl_message_codec.h" 45 | "fl_method_call.h" 46 | "fl_method_channel.h" 47 | "fl_method_codec.h" 48 | "fl_method_response.h" 49 | "fl_plugin_registrar.h" 50 | "fl_plugin_registry.h" 51 | "fl_standard_message_codec.h" 52 | "fl_standard_method_codec.h" 53 | "fl_string_codec.h" 54 | "fl_value.h" 55 | "fl_view.h" 56 | "flutter_linux.h" 57 | ) 58 | list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") 59 | add_library(flutter INTERFACE) 60 | target_include_directories(flutter INTERFACE 61 | "${EPHEMERAL_DIR}" 62 | ) 63 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") 64 | target_link_libraries(flutter INTERFACE 65 | PkgConfig::GTK 66 | PkgConfig::GLIB 67 | PkgConfig::GIO 68 | ) 69 | add_dependencies(flutter flutter_assemble) 70 | 71 | # === Flutter tool backend === 72 | # _phony_ is a non-existent file to force this command to run every time, 73 | # since currently there's no way to get a full input/output list from the 74 | # flutter tool. 75 | add_custom_command( 76 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 77 | ${CMAKE_CURRENT_BINARY_DIR}/_phony_ 78 | COMMAND ${CMAKE_COMMAND} -E env 79 | ${FLUTTER_TOOL_ENVIRONMENT} 80 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" 81 | ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} 82 | VERBATIM 83 | ) 84 | add_custom_target(flutter_assemble DEPENDS 85 | "${FLUTTER_LIBRARY}" 86 | ${FLUTTER_LIBRARY_HEADERS} 87 | ) 88 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /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 | #ifdef FLUTTER_BUILD_NUMBER 64 | #define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER 65 | #else 66 | #define VERSION_AS_NUMBER 1,0,0 67 | #endif 68 | 69 | #ifdef FLUTTER_BUILD_NAME 70 | #define VERSION_AS_STRING #FLUTTER_BUILD_NAME 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.liugl" "\0" 93 | VALUE "FileDescription", "Demonstrates how to use the flutter_switch_clipper plugin." "\0" 94 | VALUE "FileVersion", VERSION_AS_STRING "\0" 95 | VALUE "InternalName", "flutter_switch_clipper_example" "\0" 96 | VALUE "LegalCopyright", "Copyright (C) 2021 com.liugl. All rights reserved." "\0" 97 | VALUE "OriginalFilename", "flutter_switch_clipper_example.exe" "\0" 98 | VALUE "ProductName", "flutter_switch_clipper_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/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_switch_clipper_example 2 | description: Demonstrates how to use the flutter_switch_clipper plugin. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `flutter pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | environment: 9 | sdk: ">=2.12.0 <3.0.0" 10 | 11 | # Dependencies specify other packages that your package needs in order to work. 12 | # To automatically upgrade your package dependencies to the latest versions 13 | # consider running `flutter pub upgrade --major-versions`. Alternatively, 14 | # dependencies can be manually updated by changing the version numbers below to 15 | # the latest version available on pub.dev. To see which dependencies have newer 16 | # versions available, run `flutter pub outdated`. 17 | dependencies: 18 | flutter: 19 | sdk: flutter 20 | 21 | flutter_switch_clipper: 22 | # When depending on this package from a real application you should use: 23 | # flutter_switch_clipper: ^x.y.z 24 | # See https://dart.dev/tools/pub/dependencies#version-constraints 25 | # The example app is bundled with the plugin so we use a path dependency on 26 | # the parent directory to use the current plugin's version. 27 | path: ../ 28 | 29 | # The following adds the Cupertino Icons font to your application. 30 | # Use with the CupertinoIcons class for iOS style icons. 31 | cupertino_icons: ^1.0.2 32 | 33 | dev_dependencies: 34 | flutter_test: 35 | sdk: flutter 36 | 37 | # The "flutter_lints" package below contains a set of recommended lints to 38 | # encourage good coding practices. The lint set provided by the package is 39 | # activated in the `analysis_options.yaml` file located at the root of your 40 | # package. See that file for information about deactivating specific lint 41 | # rules and activating additional ones. 42 | flutter_lints: ^1.0.0 43 | 44 | # For information on the generic Dart part of this file, see the 45 | # following page: https://dart.dev/tools/pub/pubspec 46 | 47 | # The following section is specific to Flutter. 48 | flutter: 49 | 50 | # The following line ensures that the Material Icons font is 51 | # included with your application, so that you can use the icons in 52 | # the material Icons class. 53 | uses-material-design: true 54 | 55 | # To add assets to your application, add an assets section, like this: 56 | # assets: 57 | # - images/a_dot_burr.jpeg 58 | # - images/a_dot_ham.jpeg 59 | 60 | # An image asset can refer to one or more resolution-specific "variants", see 61 | # https://flutter.dev/assets-and-images/#resolution-aware. 62 | 63 | # For details regarding adding assets from package dependencies, see 64 | # https://flutter.dev/assets-and-images/#from-packages 65 | 66 | # To add custom fonts to your application, add a fonts section here, 67 | # in this "flutter" section. Each entry in this list should have a 68 | # "family" key with the font family name, and a "fonts" key with a 69 | # list giving the asset and other descriptors for the font. For 70 | # example: 71 | # fonts: 72 | # - family: Schyler 73 | # fonts: 74 | # - asset: fonts/Schyler-Regular.ttf 75 | # - asset: fonts/Schyler-Italic.ttf 76 | # style: italic 77 | # - family: Trajan Pro 78 | # fonts: 79 | # - asset: fonts/TrajanPro.ttf 80 | # - asset: fonts/TrajanPro_Bold.ttf 81 | # weight: 700 82 | # 83 | # For details regarding fonts from package dependencies, 84 | # see https://flutter.dev/custom-fonts/#from-packages 85 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /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 and shows a win32 window with |title| and position and size 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 to will treat the width height passed in to this function 35 | // as logical pixels and scale to appropriate for the default monitor. Returns 36 | // true if the window was created successfully. 37 | bool CreateAndShow(const std::wstring& title, 38 | const Point& origin, 39 | const Size& size); 40 | 41 | // Release OS resources associated with window. 42 | void Destroy(); 43 | 44 | // Inserts |content| into the window tree. 45 | void SetChildContent(HWND content); 46 | 47 | // Returns the backing Window handle to enable clients to set icon and other 48 | // window properties. Returns nullptr if the window has been destroyed. 49 | HWND GetHandle(); 50 | 51 | // If true, closing this window will quit the application. 52 | void SetQuitOnClose(bool quit_on_close); 53 | 54 | // Return a RECT representing the bounds of the current client area. 55 | RECT GetClientArea(); 56 | 57 | protected: 58 | // Processes and route salient window messages for mouse handling, 59 | // size change and DPI. Delegates handling of these to member overloads that 60 | // inheriting classes can handle. 61 | virtual LRESULT MessageHandler(HWND window, 62 | UINT const message, 63 | WPARAM const wparam, 64 | LPARAM const lparam) noexcept; 65 | 66 | // Called when CreateAndShow is called, allowing subclass window-related 67 | // setup. Subclasses should return false if setup fails. 68 | virtual bool OnCreate(); 69 | 70 | // Called when Destroy is called. 71 | virtual void OnDestroy(); 72 | 73 | private: 74 | friend class WindowClassRegistrar; 75 | 76 | // OS callback called by message pump. Handles the WM_NCCREATE message which 77 | // is passed when the non-client area is being created and enables automatic 78 | // non-client DPI scaling so that the non-client area automatically 79 | // responsponds to changes in DPI. All other messages are handled by 80 | // MessageHandler. 81 | static LRESULT CALLBACK WndProc(HWND const window, 82 | UINT const message, 83 | WPARAM const wparam, 84 | LPARAM const lparam) noexcept; 85 | 86 | // Retrieves a class instance pointer for |window| 87 | static Win32Window* GetThisFromHandle(HWND const window) noexcept; 88 | 89 | bool quit_on_close_ = false; 90 | 91 | // window handle for top level window. 92 | HWND window_handle_ = nullptr; 93 | 94 | // window handle for hosted content. 95 | HWND child_content_ = nullptr; 96 | }; 97 | 98 | #endif // RUNNER_WIN32_WINDOW_H_ 99 | -------------------------------------------------------------------------------- /example/windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(flutter_switch_clipper_example LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "flutter_switch_clipper_example") 5 | 6 | cmake_policy(SET CMP0063 NEW) 7 | 8 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 9 | 10 | # Configure build options. 11 | get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 12 | if(IS_MULTICONFIG) 13 | set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" 14 | CACHE STRING "" FORCE) 15 | else() 16 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 17 | set(CMAKE_BUILD_TYPE "Debug" CACHE 18 | STRING "Flutter build mode" FORCE) 19 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 20 | "Debug" "Profile" "Release") 21 | endif() 22 | endif() 23 | 24 | set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") 25 | set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") 26 | set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") 27 | set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") 28 | 29 | # Use Unicode for all projects. 30 | add_definitions(-DUNICODE -D_UNICODE) 31 | 32 | # Compilation settings that should be applied to most targets. 33 | function(APPLY_STANDARD_SETTINGS TARGET) 34 | target_compile_features(${TARGET} PUBLIC cxx_std_17) 35 | target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") 36 | target_compile_options(${TARGET} PRIVATE /EHsc) 37 | target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") 38 | target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") 39 | endfunction() 40 | 41 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 42 | 43 | # Flutter library and tool build rules. 44 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 45 | 46 | # Application build 47 | add_subdirectory("runner") 48 | 49 | # Generated plugin build rules, which manage building the plugins and adding 50 | # them to the application. 51 | include(flutter/generated_plugins.cmake) 52 | 53 | 54 | # === Installation === 55 | # Support files are copied into place next to the executable, so that it can 56 | # run in place. This is done instead of making a separate bundle (as on Linux) 57 | # so that building and running from within Visual Studio will work. 58 | set(BUILD_BUNDLE_DIR "$") 59 | # Make the "install" step default, as it's required to run. 60 | set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) 61 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 62 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 63 | endif() 64 | 65 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 66 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") 67 | 68 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 69 | COMPONENT Runtime) 70 | 71 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 72 | COMPONENT Runtime) 73 | 74 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 75 | COMPONENT Runtime) 76 | 77 | if(PLUGIN_BUNDLED_LIBRARIES) 78 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 79 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 80 | COMPONENT Runtime) 81 | endif() 82 | 83 | # Fully re-copy the assets directory on each build to avoid having stale files 84 | # from a previous install. 85 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 86 | install(CODE " 87 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 88 | " COMPONENT Runtime) 89 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 90 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 91 | 92 | # Install the AOT library on non-Debug builds only. 93 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 94 | CONFIGURATIONS Profile;Release 95 | COMPONENT Runtime) 96 | -------------------------------------------------------------------------------- /example/windows/flutter/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") 4 | 5 | # Configuration provided via flutter tool. 6 | include(${EPHEMERAL_DIR}/generated_config.cmake) 7 | 8 | # TODO: Move the rest of this into files in ephemeral. See 9 | # https://github.com/flutter/flutter/issues/57146. 10 | set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") 11 | 12 | # === Flutter Library === 13 | set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") 14 | 15 | # Published to parent scope for install step. 16 | set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) 17 | set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) 18 | set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) 19 | set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) 20 | 21 | list(APPEND FLUTTER_LIBRARY_HEADERS 22 | "flutter_export.h" 23 | "flutter_windows.h" 24 | "flutter_messenger.h" 25 | "flutter_plugin_registrar.h" 26 | "flutter_texture_registrar.h" 27 | ) 28 | list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") 29 | add_library(flutter INTERFACE) 30 | target_include_directories(flutter INTERFACE 31 | "${EPHEMERAL_DIR}" 32 | ) 33 | target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") 34 | add_dependencies(flutter flutter_assemble) 35 | 36 | # === Wrapper === 37 | list(APPEND CPP_WRAPPER_SOURCES_CORE 38 | "core_implementations.cc" 39 | "standard_codec.cc" 40 | ) 41 | list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") 42 | list(APPEND CPP_WRAPPER_SOURCES_PLUGIN 43 | "plugin_registrar.cc" 44 | ) 45 | list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") 46 | list(APPEND CPP_WRAPPER_SOURCES_APP 47 | "flutter_engine.cc" 48 | "flutter_view_controller.cc" 49 | ) 50 | list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") 51 | 52 | # Wrapper sources needed for a plugin. 53 | add_library(flutter_wrapper_plugin STATIC 54 | ${CPP_WRAPPER_SOURCES_CORE} 55 | ${CPP_WRAPPER_SOURCES_PLUGIN} 56 | ) 57 | apply_standard_settings(flutter_wrapper_plugin) 58 | set_target_properties(flutter_wrapper_plugin PROPERTIES 59 | POSITION_INDEPENDENT_CODE ON) 60 | set_target_properties(flutter_wrapper_plugin PROPERTIES 61 | CXX_VISIBILITY_PRESET hidden) 62 | target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) 63 | target_include_directories(flutter_wrapper_plugin PUBLIC 64 | "${WRAPPER_ROOT}/include" 65 | ) 66 | add_dependencies(flutter_wrapper_plugin flutter_assemble) 67 | 68 | # Wrapper sources needed for the runner. 69 | add_library(flutter_wrapper_app STATIC 70 | ${CPP_WRAPPER_SOURCES_CORE} 71 | ${CPP_WRAPPER_SOURCES_APP} 72 | ) 73 | apply_standard_settings(flutter_wrapper_app) 74 | target_link_libraries(flutter_wrapper_app PUBLIC flutter) 75 | target_include_directories(flutter_wrapper_app PUBLIC 76 | "${WRAPPER_ROOT}/include" 77 | ) 78 | add_dependencies(flutter_wrapper_app flutter_assemble) 79 | 80 | # === Flutter tool backend === 81 | # _phony_ is a non-existent file to force this command to run every time, 82 | # since currently there's no way to get a full input/output list from the 83 | # flutter tool. 84 | set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") 85 | set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) 86 | add_custom_command( 87 | OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} 88 | ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} 89 | ${CPP_WRAPPER_SOURCES_APP} 90 | ${PHONY_OUTPUT} 91 | COMMAND ${CMAKE_COMMAND} -E env 92 | ${FLUTTER_TOOL_ENVIRONMENT} 93 | "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" 94 | windows-x64 $ 95 | VERBATIM 96 | ) 97 | add_custom_target(flutter_assemble DEPENDS 98 | "${FLUTTER_LIBRARY}" 99 | ${FLUTTER_LIBRARY_HEADERS} 100 | ${CPP_WRAPPER_SOURCES_CORE} 101 | ${CPP_WRAPPER_SOURCES_PLUGIN} 102 | ${CPP_WRAPPER_SOURCES_APP} 103 | ) 104 | -------------------------------------------------------------------------------- /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, "flutter_switch_clipper_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, "flutter_switch_clipper_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/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | flutter_switch_clipper_example 30 | 31 | 32 | 33 | 36 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /example/linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(runner LANGUAGES CXX) 3 | 4 | set(BINARY_NAME "flutter_switch_clipper_example") 5 | set(APPLICATION_ID "com.liugl.flutter_switch_clipper") 6 | 7 | cmake_policy(SET CMP0063 NEW) 8 | 9 | set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") 10 | 11 | # Root filesystem for cross-building. 12 | if(FLUTTER_TARGET_PLATFORM_SYSROOT) 13 | set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) 14 | set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 18 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 19 | endif() 20 | 21 | # Configure build options. 22 | if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 23 | set(CMAKE_BUILD_TYPE "Debug" CACHE 24 | STRING "Flutter build mode" FORCE) 25 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS 26 | "Debug" "Profile" "Release") 27 | endif() 28 | 29 | # Compilation settings that should be applied to most targets. 30 | function(APPLY_STANDARD_SETTINGS TARGET) 31 | target_compile_features(${TARGET} PUBLIC cxx_std_14) 32 | target_compile_options(${TARGET} PRIVATE -Wall -Werror) 33 | target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") 34 | target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") 35 | endfunction() 36 | 37 | set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") 38 | 39 | # Flutter library and tool build rules. 40 | add_subdirectory(${FLUTTER_MANAGED_DIR}) 41 | 42 | # System-level dependencies. 43 | find_package(PkgConfig REQUIRED) 44 | pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) 45 | 46 | add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") 47 | 48 | # Application build 49 | add_executable(${BINARY_NAME} 50 | "main.cc" 51 | "my_application.cc" 52 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 53 | ) 54 | apply_standard_settings(${BINARY_NAME}) 55 | target_link_libraries(${BINARY_NAME} PRIVATE flutter) 56 | target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) 57 | add_dependencies(${BINARY_NAME} flutter_assemble) 58 | # Only the install-generated bundle's copy of the executable will launch 59 | # correctly, since the resources must in the right relative locations. To avoid 60 | # people trying to run the unbundled copy, put it in a subdirectory instead of 61 | # the default top-level location. 62 | set_target_properties(${BINARY_NAME} 63 | PROPERTIES 64 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" 65 | ) 66 | 67 | # Generated plugin build rules, which manage building the plugins and adding 68 | # them to the application. 69 | include(flutter/generated_plugins.cmake) 70 | 71 | 72 | # === Installation === 73 | # By default, "installing" just makes a relocatable bundle in the build 74 | # directory. 75 | set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") 76 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 77 | set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) 78 | endif() 79 | 80 | # Start with a clean build bundle directory every time. 81 | install(CODE " 82 | file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") 83 | " COMPONENT Runtime) 84 | 85 | set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") 86 | set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") 87 | 88 | install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" 89 | COMPONENT Runtime) 90 | 91 | install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" 92 | COMPONENT Runtime) 93 | 94 | install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 95 | COMPONENT Runtime) 96 | 97 | if(PLUGIN_BUNDLED_LIBRARIES) 98 | install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" 99 | DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 100 | COMPONENT Runtime) 101 | endif() 102 | 103 | # Fully re-copy the assets directory on each build to avoid having stale files 104 | # from a previous install. 105 | set(FLUTTER_ASSET_DIR_NAME "flutter_assets") 106 | install(CODE " 107 | file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") 108 | " COMPONENT Runtime) 109 | install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" 110 | DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) 111 | 112 | # Install the AOT library on non-Debug builds only. 113 | if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") 114 | install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" 115 | COMPONENT Runtime) 116 | endif() 117 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_switch_clipper/flutter_switch_clipper.dart'; 3 | 4 | void main() { 5 | runApp(const MyApp()); 6 | } 7 | 8 | class MyApp extends StatefulWidget { 9 | const MyApp({Key? key}) : super(key: key); 10 | 11 | @override 12 | State createState() => _MyAppState(); 13 | } 14 | 15 | class _MyAppState extends State { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | home: Scaffold( 20 | backgroundColor: Colors.blueGrey[200], 21 | appBar: AppBar( 22 | title: const Text('Plugin example app'), 23 | ), 24 | body: ListView( 25 | padding: const EdgeInsets.all(40), 26 | children: [ 27 | const SwitchClipper( 28 | initSelect: true, 29 | child: Icon(Icons.favorite, size: 200, color: Colors.redAccent), 30 | background: Icon(Icons.favorite, size: 200, color: Colors.white), 31 | duration: Duration(milliseconds: 800), 32 | 33 | /// 使用FillClipper并自定义相关参数 34 | animationClip: FillClipper(fillOffset: 50), 35 | ), 36 | 37 | /// 默认FillClipper 38 | const SwitchClipper( 39 | enableWhenAnimating: false, 40 | child: Text( 41 | 'FlutterCandies', 42 | style: TextStyle( 43 | fontWeight: FontWeight.bold, 44 | fontSize: 50, 45 | color: Colors.amber, 46 | height: 2, 47 | ), 48 | ), 49 | background: Text( 50 | 'FlutterCandies', 51 | style: TextStyle( 52 | fontWeight: FontWeight.bold, 53 | fontSize: 50, 54 | color: Colors.white, 55 | height: 2, 56 | ), 57 | ), 58 | curve: Curves.slowMiddle, 59 | reverseCurve: Curves.linear, 60 | ), 61 | 62 | Wrap( 63 | children: [ 64 | /// 使用ShutterClipper 65 | SwitchClipper( 66 | child: ColoredBox( 67 | color: Colors.blueGrey[200] ?? Colors.blueGrey, 68 | child: const Icon(Icons.accessibility_new_rounded, 69 | size: 200, color: Colors.white), 70 | ), 71 | background: const Icon(Icons.accessible_forward_outlined, 72 | size: 200, color: Colors.white), 73 | curve: Curves.ease, 74 | duration: const Duration(milliseconds: 800), 75 | animationClip: ShutterClipper(), 76 | ), 77 | 78 | /// 使用CircleClipper切换图标颜色 79 | SwitchClipper( 80 | child: const Icon(Icons.accessibility_new_rounded, 81 | size: 200, color: Colors.blueAccent), 82 | background: const Icon(Icons.accessibility_new_rounded, 83 | size: 200, color: Colors.white), 84 | curve: Curves.ease, 85 | duration: const Duration(milliseconds: 800), 86 | animationClip: CircleClipper(), 87 | ), 88 | 89 | /// 使用CircleClipper切换两个图标 90 | SwitchClipper( 91 | child: ColoredBox( 92 | color: Colors.blueGrey[200] ?? Colors.blueGrey, 93 | child: const Icon(Icons.accessibility_new_rounded, 94 | size: 200, color: Colors.white), 95 | ), 96 | background: const Icon(Icons.accessible_forward_outlined, 97 | size: 200, color: Colors.white), 98 | curve: Curves.ease, 99 | duration: const Duration(milliseconds: 800), 100 | animationClip: CircleClipper(), 101 | ), 102 | 103 | /// 使用WaveClipper切换图标颜色 104 | SwitchClipper( 105 | child: const Icon(Icons.access_time_filled_rounded, 106 | size: 200, color: Colors.blue), 107 | // child: Container(width: 200, height: 200, color: Colors.blue), 108 | background: const Icon(Icons.access_time_filled_rounded, 109 | size: 200, color: Colors.white), 110 | curve: Curves.ease, 111 | duration: const Duration(milliseconds: 2000), 112 | animationClip: WaveClipper(), 113 | ), 114 | 115 | /// 使用CameraClipper切换图标颜色 116 | SwitchClipper( 117 | // child: const Icon(Icons.access_time_filled_rounded, size: 200, color: Colors.blue), 118 | child: Container( 119 | width: 200, 120 | height: 200, 121 | alignment: Alignment.center, 122 | decoration: const BoxDecoration( 123 | shape: BoxShape.circle, 124 | color: Colors.blue, 125 | ), 126 | child: const Text( 127 | 'Camera', 128 | style: TextStyle( 129 | color: Colors.white, 130 | fontSize: 40, 131 | fontWeight: FontWeight.bold), 132 | ), 133 | ), 134 | // background: const Icon(Icons.access_time_filled_rounded, size: 200, color: Colors.white), 135 | background: Container( 136 | width: 200, 137 | height: 200, 138 | decoration: const BoxDecoration( 139 | shape: BoxShape.circle, 140 | color: Colors.white, 141 | ), 142 | ), 143 | duration: const Duration(milliseconds: 1500), 144 | animationClip: CameraClipper(), 145 | ), 146 | ], 147 | ), 148 | const SizedBox(height: 40), 149 | 150 | const Text('点击上方图标或文本预览效果'), 151 | ], 152 | ), 153 | ), 154 | ); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Flutter Switch Clipper 2 | 3 | A Flutter package that two widgets switch with clipper. 4 | 5 | [![pub package](https://img.shields.io/pub/v/flutter_switch_clipper?logo=dart&label=stable&style=flat-square)](https://pub.dev/packages/flutter_switch_clipper) 6 | [![GitHub stars](https://img.shields.io/github/stars/fluttercandies/flutter_switch_clipper?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_switch_clipper/stargazers) 7 | [![GitHub forks](https://img.shields.io/github/forks/fluttercandies/flutter_switch_clipper?logo=github&style=flat-square)](https://github.com/fluttercandies/flutter_switch_clipper/network/members) 8 | [![CodeFactor](https://img.shields.io/codefactor/grade/github/fluttercandies/flutter_switch_clipper?logo=codefactor&logoColor=%23ffffff&style=flat-square)](https://www.codefactor.io/repository/github/fluttercandies/flutter_switch_clipper) 9 | FlutterCandies 10 | 11 | 12 | ### 体验一下 13 | 14 | 体验网址:[Demo](https://xsilencex.github.io/flutter_switch_clipper_demo/) 15 | 16 | ### 使用 17 | 18 | > 使用FillClipper并自定义相关参数 19 | 20 | 21 |
22 | View code 23 | 24 | ```dart 25 | SwitchClipper( 26 | initSelect: true, 27 | child: const Icon(Icons.favorite, size: 200, color: Colors.redAccent), 28 | background: const Icon(Icons.favorite, size: 200, color: Colors.white), 29 | duration: const Duration(milliseconds: 800), 30 | animationClip: FillClipper(fillAlignment: _alignment,fillOffset: 50), 31 | ), 32 | ``` 33 |
34 | 35 |
36 | 37 | > 使用默认FillClipper 38 | 39 | 40 | 41 |
42 | View code 43 | 44 | ```dart 45 | const SwitchClipper( 46 | enableWhenAnimating: false, 47 | child: Text( 48 | 'FlutterCandies', 49 | style: TextStyle( 50 | fontWeight: FontWeight.bold, 51 | fontSize: 50, 52 | color: Colors.amber, 53 | height: 2, 54 | ), 55 | ), 56 | background: Text( 57 | 'FlutterCandies', 58 | style: TextStyle( 59 | fontWeight: FontWeight.bold, 60 | fontSize: 50, 61 | color: Colors.white, 62 | height: 2, 63 | ), 64 | ), 65 | curve: Curves.slowMiddle, 66 | reverseCurve: Curves.linear, 67 | ), 68 | ``` 69 | 70 |
71 | 72 |
73 | 74 | > 使用CircleClipper切换图标颜色 75 | 76 | 77 | 78 |
79 | View code 80 | 81 | ```dart 82 | SwitchClipper( 83 | child: const Icon(Icons.accessibility_new_rounded, size: 200, color: Colors.blueAccent), 84 | background: const Icon(Icons.accessibility_new_rounded, size: 200, color: Colors.white), 85 | curve: Curves.ease, 86 | duration: const Duration(milliseconds: 800), 87 | animationClip: CircleClipper(), 88 | ), 89 | ``` 90 | 91 |
92 | 93 |
94 | 95 | > 使用CircleClipper切换两个图标 96 | 97 | 98 | 99 |
100 | View code 101 | 102 | ```dart 103 | SwitchClipper( 104 | child: ColoredBox( 105 | color: Colors.blueGrey[200] ?? Colors.blueGrey, 106 | child: const Icon(Icons.accessibility_new_rounded, size: 200, color: Colors.white)), 107 | background: const Icon(Icons.accessible_forward_outlined, size: 200, color: Colors.white), 108 | curve: Curves.ease, 109 | duration: const Duration(milliseconds: 800), 110 | animationClip: CircleClipper(), 111 | ), 112 | ``` 113 | 114 |
115 | 116 |
117 | 118 | > 使用ShutterClipper 119 | 120 | 121 | 122 |
123 | View code 124 | 125 | ```dart 126 | SwitchClipper( 127 | child: ColoredBox( 128 | color: Colors.blueGrey[200] ?? Colors.blueGrey, 129 | child: const Icon(Icons.accessibility_new_rounded, size: 200, color: Colors.white)), 130 | background: const Icon(Icons.accessible_forward_outlined, size: 200, color: Colors.white), 131 | curve: Curves.ease, 132 | duration: const Duration(milliseconds: 800), 133 | animationClip: ShutterClipper(activeAlignment: _alignment), 134 | ), 135 | ``` 136 | 137 |
138 | 139 |
140 | 141 | > 使用WaveClipper 142 | 143 | 144 | 145 |
146 | View code 147 | 148 | ```dart 149 | SwitchClipper( 150 | child: const Icon(Icons.access_time_filled_rounded, size: 200, color: Colors.blue), 151 | background: const Icon(Icons.access_time_filled_rounded, size: 200, color: Colors.white), 152 | curve: Curves.ease, 153 | duration: const Duration(milliseconds: 2000), 154 | animationClip: WaveClipper( 155 | waveAlignment: _alignment == FillAlignment.left ? WaveAlignment.left : WaveAlignment.right, 156 | ), 157 | ), 158 | ``` 159 | 160 |
161 | 162 |
163 | 164 | > 使用CameraClipper 165 | 166 | 167 | 168 |
169 | View code 170 | 171 | ```dart 172 | SwitchClipper( 173 | child: Container( 174 | width: 200, 175 | height: 200, 176 | alignment: Alignment.center, 177 | decoration: const BoxDecoration( 178 | shape: BoxShape.circle, 179 | color: Colors.blue, 180 | ), 181 | child: const Text( 182 | 'Camera', 183 | style: TextStyle(color: Colors.white, fontSize: 40, fontWeight: FontWeight.bold), 184 | ), 185 | ), 186 | background: Container( 187 | width: 200, 188 | height: 200, 189 | decoration: const BoxDecoration( 190 | shape: BoxShape.circle, 191 | color: Colors.white, 192 | ), 193 | ), 194 | duration: const Duration(milliseconds: 2000), 195 | animationClip: CameraClipper(), 196 | ), 197 | ``` 198 | 199 |
200 | 201 | 202 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | fake_async: 45 | dependency: transitive 46 | description: 47 | name: fake_async 48 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.3.3" 52 | flutter: 53 | dependency: "direct main" 54 | description: flutter 55 | source: sdk 56 | version: "0.0.0" 57 | flutter_lints: 58 | dependency: "direct dev" 59 | description: 60 | name: flutter_lints 61 | sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 62 | url: "https://pub.dev" 63 | source: hosted 64 | version: "1.0.4" 65 | flutter_test: 66 | dependency: "direct dev" 67 | description: flutter 68 | source: sdk 69 | version: "0.0.0" 70 | leak_tracker: 71 | dependency: transitive 72 | description: 73 | name: leak_tracker 74 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 75 | url: "https://pub.dev" 76 | source: hosted 77 | version: "10.0.9" 78 | leak_tracker_flutter_testing: 79 | dependency: transitive 80 | description: 81 | name: leak_tracker_flutter_testing 82 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 83 | url: "https://pub.dev" 84 | source: hosted 85 | version: "3.0.9" 86 | leak_tracker_testing: 87 | dependency: transitive 88 | description: 89 | name: leak_tracker_testing 90 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 91 | url: "https://pub.dev" 92 | source: hosted 93 | version: "3.0.1" 94 | lints: 95 | dependency: transitive 96 | description: 97 | name: lints 98 | sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c 99 | url: "https://pub.dev" 100 | source: hosted 101 | version: "1.0.1" 102 | matcher: 103 | dependency: transitive 104 | description: 105 | name: matcher 106 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 107 | url: "https://pub.dev" 108 | source: hosted 109 | version: "0.12.17" 110 | material_color_utilities: 111 | dependency: transitive 112 | description: 113 | name: material_color_utilities 114 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 115 | url: "https://pub.dev" 116 | source: hosted 117 | version: "0.11.1" 118 | meta: 119 | dependency: transitive 120 | description: 121 | name: meta 122 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 123 | url: "https://pub.dev" 124 | source: hosted 125 | version: "1.16.0" 126 | path: 127 | dependency: transitive 128 | description: 129 | name: path 130 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 131 | url: "https://pub.dev" 132 | source: hosted 133 | version: "1.9.1" 134 | sky_engine: 135 | dependency: transitive 136 | description: flutter 137 | source: sdk 138 | version: "0.0.0" 139 | source_span: 140 | dependency: transitive 141 | description: 142 | name: source_span 143 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 144 | url: "https://pub.dev" 145 | source: hosted 146 | version: "1.10.1" 147 | stack_trace: 148 | dependency: transitive 149 | description: 150 | name: stack_trace 151 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 152 | url: "https://pub.dev" 153 | source: hosted 154 | version: "1.12.1" 155 | stream_channel: 156 | dependency: transitive 157 | description: 158 | name: stream_channel 159 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 160 | url: "https://pub.dev" 161 | source: hosted 162 | version: "2.1.4" 163 | string_scanner: 164 | dependency: transitive 165 | description: 166 | name: string_scanner 167 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 168 | url: "https://pub.dev" 169 | source: hosted 170 | version: "1.4.1" 171 | term_glyph: 172 | dependency: transitive 173 | description: 174 | name: term_glyph 175 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 176 | url: "https://pub.dev" 177 | source: hosted 178 | version: "1.2.2" 179 | test_api: 180 | dependency: transitive 181 | description: 182 | name: test_api 183 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 184 | url: "https://pub.dev" 185 | source: hosted 186 | version: "0.7.4" 187 | vector_math: 188 | dependency: transitive 189 | description: 190 | name: vector_math 191 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 192 | url: "https://pub.dev" 193 | source: hosted 194 | version: "2.1.4" 195 | vm_service: 196 | dependency: transitive 197 | description: 198 | name: vm_service 199 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 200 | url: "https://pub.dev" 201 | source: hosted 202 | version: "15.0.0" 203 | sdks: 204 | dart: ">=3.7.0-0 <4.0.0" 205 | flutter: ">=3.18.0-18.0.pre.54" 206 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.13.0" 12 | boolean_selector: 13 | dependency: transitive 14 | description: 15 | name: boolean_selector 16 | sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "2.1.2" 20 | characters: 21 | dependency: transitive 22 | description: 23 | name: characters 24 | sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.4.0" 28 | clock: 29 | dependency: transitive 30 | description: 31 | name: clock 32 | sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "1.1.2" 36 | collection: 37 | dependency: transitive 38 | description: 39 | name: collection 40 | sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "1.19.1" 44 | cupertino_icons: 45 | dependency: "direct main" 46 | description: 47 | name: cupertino_icons 48 | sha256: "1989d917fbe8e6b39806207df5a3fdd3d816cbd090fac2ce26fb45e9a71476e5" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.0.4" 52 | fake_async: 53 | dependency: transitive 54 | description: 55 | name: fake_async 56 | sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.3.3" 60 | flutter: 61 | dependency: "direct main" 62 | description: flutter 63 | source: sdk 64 | version: "0.0.0" 65 | flutter_lints: 66 | dependency: "direct dev" 67 | description: 68 | name: flutter_lints 69 | sha256: b543301ad291598523947dc534aaddc5aaad597b709d2426d3a0e0d44c5cb493 70 | url: "https://pub.dev" 71 | source: hosted 72 | version: "1.0.4" 73 | flutter_switch_clipper: 74 | dependency: "direct main" 75 | description: 76 | path: ".." 77 | relative: true 78 | source: path 79 | version: "0.0.6" 80 | flutter_test: 81 | dependency: "direct dev" 82 | description: flutter 83 | source: sdk 84 | version: "0.0.0" 85 | leak_tracker: 86 | dependency: transitive 87 | description: 88 | name: leak_tracker 89 | sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0" 90 | url: "https://pub.dev" 91 | source: hosted 92 | version: "10.0.9" 93 | leak_tracker_flutter_testing: 94 | dependency: transitive 95 | description: 96 | name: leak_tracker_flutter_testing 97 | sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 98 | url: "https://pub.dev" 99 | source: hosted 100 | version: "3.0.9" 101 | leak_tracker_testing: 102 | dependency: transitive 103 | description: 104 | name: leak_tracker_testing 105 | sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" 106 | url: "https://pub.dev" 107 | source: hosted 108 | version: "3.0.1" 109 | lints: 110 | dependency: transitive 111 | description: 112 | name: lints 113 | sha256: a2c3d198cb5ea2e179926622d433331d8b58374ab8f29cdda6e863bd62fd369c 114 | url: "https://pub.dev" 115 | source: hosted 116 | version: "1.0.1" 117 | matcher: 118 | dependency: transitive 119 | description: 120 | name: matcher 121 | sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 122 | url: "https://pub.dev" 123 | source: hosted 124 | version: "0.12.17" 125 | material_color_utilities: 126 | dependency: transitive 127 | description: 128 | name: material_color_utilities 129 | sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec 130 | url: "https://pub.dev" 131 | source: hosted 132 | version: "0.11.1" 133 | meta: 134 | dependency: transitive 135 | description: 136 | name: meta 137 | sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c 138 | url: "https://pub.dev" 139 | source: hosted 140 | version: "1.16.0" 141 | path: 142 | dependency: transitive 143 | description: 144 | name: path 145 | sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 146 | url: "https://pub.dev" 147 | source: hosted 148 | version: "1.9.1" 149 | sky_engine: 150 | dependency: transitive 151 | description: flutter 152 | source: sdk 153 | version: "0.0.0" 154 | source_span: 155 | dependency: transitive 156 | description: 157 | name: source_span 158 | sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 159 | url: "https://pub.dev" 160 | source: hosted 161 | version: "1.10.1" 162 | stack_trace: 163 | dependency: transitive 164 | description: 165 | name: stack_trace 166 | sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 167 | url: "https://pub.dev" 168 | source: hosted 169 | version: "1.12.1" 170 | stream_channel: 171 | dependency: transitive 172 | description: 173 | name: stream_channel 174 | sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 175 | url: "https://pub.dev" 176 | source: hosted 177 | version: "2.1.4" 178 | string_scanner: 179 | dependency: transitive 180 | description: 181 | name: string_scanner 182 | sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 183 | url: "https://pub.dev" 184 | source: hosted 185 | version: "1.4.1" 186 | term_glyph: 187 | dependency: transitive 188 | description: 189 | name: term_glyph 190 | sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 191 | url: "https://pub.dev" 192 | source: hosted 193 | version: "1.2.2" 194 | test_api: 195 | dependency: transitive 196 | description: 197 | name: test_api 198 | sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd 199 | url: "https://pub.dev" 200 | source: hosted 201 | version: "0.7.4" 202 | vector_math: 203 | dependency: transitive 204 | description: 205 | name: vector_math 206 | sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" 207 | url: "https://pub.dev" 208 | source: hosted 209 | version: "2.1.4" 210 | vm_service: 211 | dependency: transitive 212 | description: 213 | name: vm_service 214 | sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02 215 | url: "https://pub.dev" 216 | source: hosted 217 | version: "15.0.0" 218 | sdks: 219 | dart: ">=3.7.0-0 <4.0.0" 220 | flutter: ">=3.18.0-18.0.pre.54" 221 | -------------------------------------------------------------------------------- /lib/src/switch_clipper.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'clippers/animation_clipper.dart'; 4 | import 'clippers/fill_clipper.dart'; 5 | 6 | /// 动画执行状态回调 7 | typedef OnAnimationStatusChanged = void Function(AnimationStatus animationStatus); 8 | 9 | /// SwitchClipper 10 | class SwitchClipper extends StatefulWidget { 11 | const SwitchClipper({ 12 | Key? key, 13 | required this.child, 14 | required this.background, 15 | this.duration = const Duration(milliseconds: 500), 16 | this.curve = Curves.bounceOut, 17 | this.reverseCurve = Curves.ease, 18 | this.isSelect, 19 | this.onSelect, 20 | this.alignment = Alignment.center, 21 | this.animationClip, 22 | this.initSelect = false, 23 | this.onAnimationComplate, 24 | this.value, 25 | this.hasAnimationWhenValueChanged = true, 26 | this.enableWhenAnimating = true, 27 | }) : super(key: key); 28 | 29 | @override 30 | State createState() => _SwitchClipperState(); 31 | 32 | /// 上层Widget 33 | final Widget child; 34 | 35 | /// 底层Widget 36 | final Widget background; 37 | 38 | /// * 动画持续时间 39 | /// * 默认 `const Duration(milliseconds: 500)` 40 | final Duration duration; 41 | 42 | /// * forward动画曲线 43 | /// * 默认`Curves.bounceOut` 44 | final Curve curve; 45 | 46 | /// * reverse动画曲线 47 | /// * 默认`Curves.ease` 48 | final Curve reverseCurve; 49 | 50 | /// * 选中状态 51 | /// * `isSelect!=null` 时 `onSelect` 将失效 52 | final bool? isSelect; 53 | 54 | /// * 当前值 55 | /// * 会覆盖 `isSelect` 和 `initSelect` 56 | final double? value; 57 | 58 | /// * value变化时是否有动画 59 | /// * 默认`true` 60 | final bool hasAnimationWhenValueChanged; 61 | 62 | /// * 初始化选中状态 63 | /// * 仅在widget创建时生效 64 | /// * 默认`false` 65 | final bool initSelect; 66 | 67 | /// * 点击回调 68 | /// * `result` 回调值 69 | /// * 函数返回值将控制此次点击是否生效 70 | final bool? Function(bool result)? onSelect; 71 | 72 | /// * `child` 和 `background` 的对齐方式 73 | /// * 默认 `Alignment.center` 74 | final AlignmentGeometry alignment; 75 | 76 | /// * 自定义裁切 77 | /// * 默认 `FillClipper` 78 | final AnimationClip? animationClip; 79 | 80 | /// 动画执行状态回调 81 | final OnAnimationStatusChanged? onAnimationComplate; 82 | 83 | /// * 动画能否被打断 84 | /// * `if(!enableWhenAnimating)` 动画必须执行完毕才能进行下一步动作 85 | /// * 默认 `true` 86 | final bool enableWhenAnimating; 87 | } 88 | 89 | class _SwitchClipperState extends State with SingleTickerProviderStateMixin { 90 | /// 动画控制器 91 | late AnimationController _controller; 92 | 93 | @override 94 | void initState() { 95 | super.initState(); 96 | _initClipper(); 97 | } 98 | 99 | @override 100 | void didUpdateWidget(covariant SwitchClipper oldWidget) { 101 | super.didUpdateWidget(oldWidget); 102 | _handleUpdate(oldWidget); 103 | } 104 | 105 | @override 106 | void dispose() { 107 | _controller.dispose(); 108 | super.dispose(); 109 | } 110 | 111 | /// 初始化 112 | void _initClipper() { 113 | _controller = AnimationController( 114 | value: widget.value ?? (widget.initSelect ? 1.0 : 0.0), 115 | vsync: this, 116 | duration: widget.duration, 117 | ); 118 | 119 | _handleValue(); 120 | 121 | if (widget.value == null && widget.initSelect) { 122 | _controller.forward(); 123 | widget.onAnimationComplate?.call(AnimationStatus.completed); 124 | } 125 | } 126 | 127 | /// 处理外部更新 128 | void _handleUpdate(covariant SwitchClipper oldWidget) { 129 | if (widget.duration != oldWidget.duration) { 130 | _controller.duration = widget.duration; 131 | } 132 | 133 | if (widget.value != null && widget.value != oldWidget.value) { 134 | _handleValue(old: oldWidget.value, now: widget.value); 135 | } else { 136 | if (widget.isSelect != null && widget.isSelect != oldWidget.isSelect) { 137 | if (widget.isSelect!) { 138 | _forward(); 139 | } else { 140 | _reverse(); 141 | } 142 | } 143 | } 144 | } 145 | 146 | /// * 处理 `widget.value` 147 | Future _handleValue({double? old, double? now}) async { 148 | if (widget.value == null) return; 149 | 150 | //新旧值都存在时,判断动画方向 151 | if (old != null && now != null && widget.hasAnimationWhenValueChanged) { 152 | if (now > old) { 153 | //forward 154 | if (now >= 1) { 155 | _controller.animateTo(1.0); 156 | widget.onAnimationComplate?.call(AnimationStatus.completed); 157 | } else { 158 | _controller.animateTo(now); 159 | } 160 | } else { 161 | //reverse 162 | if (now <= 0) { 163 | _controller.animateBack(0.0); 164 | widget.onAnimationComplate?.call(AnimationStatus.dismissed); 165 | } else { 166 | _controller.animateBack(now); 167 | } 168 | } 169 | } else if (widget.value! <= 0) { 170 | _controller.value = 0.0; 171 | _controller.reverse(); 172 | widget.onAnimationComplate?.call(AnimationStatus.dismissed); 173 | } else if (widget.value! >= 1) { 174 | _controller.value = 1.0; 175 | _controller.forward(); 176 | widget.onAnimationComplate?.call(AnimationStatus.completed); 177 | } else { 178 | _controller.value = widget.value!; 179 | } 180 | } 181 | 182 | /// reverse 183 | Future _reverse() async { 184 | widget.onAnimationComplate?.call(AnimationStatus.reverse); 185 | await _controller.reverse(); 186 | widget.onAnimationComplate?.call(AnimationStatus.dismissed); 187 | } 188 | 189 | /// forward 190 | Future _forward() async { 191 | widget.onAnimationComplate?.call(AnimationStatus.forward); 192 | await _controller.forward(); 193 | widget.onAnimationComplate?.call(AnimationStatus.completed); 194 | } 195 | 196 | /// 点击回调 197 | Future _onSelect() async { 198 | if (!widget.enableWhenAnimating) { 199 | if (_controller.isCompleted) { 200 | if (!(widget.onSelect?.call(false) ?? true)) return; 201 | await _reverse(); 202 | } else if (_controller.isDismissed) { 203 | if (!(widget.onSelect?.call(true) ?? true)) return; 204 | await _forward(); 205 | } 206 | } else { 207 | if (_controller.status == AnimationStatus.reverse || _controller.isDismissed) { 208 | await _forward(); 209 | } else if (_controller.status == AnimationStatus.forward || _controller.isCompleted) { 210 | await _reverse(); 211 | } 212 | } 213 | } 214 | 215 | @override 216 | Widget build(BuildContext context) { 217 | Widget child = Stack( 218 | alignment: widget.alignment, 219 | children: [ 220 | widget.background, 221 | ClipPath(clipper: _clipper, child: widget.child), 222 | ], 223 | ); 224 | 225 | if (widget.isSelect == null) { 226 | child = GestureDetector( 227 | onTap: _onSelect, 228 | child: child, 229 | ); 230 | } 231 | 232 | return child; 233 | } 234 | 235 | ///自定义裁切 236 | CustomClipper get _clipper => _Clipper( 237 | CurvedAnimation( 238 | parent: _controller, 239 | curve: widget.curve, 240 | reverseCurve: widget.reverseCurve, 241 | ), 242 | widget.animationClip ?? const FillClipper(), 243 | ); 244 | } 245 | 246 | class _Clipper extends CustomClipper { 247 | const _Clipper( 248 | this.animation, 249 | this.animationClip, 250 | ) : super(reclip: animation); 251 | 252 | final Animation animation; 253 | 254 | final AnimationClip animationClip; 255 | 256 | @override 257 | Path getClip(Size size) { 258 | return animationClip.getClip(size, animation); 259 | } 260 | 261 | @override 262 | bool shouldReclip(covariant CustomClipper oldClipper) => false; 263 | } 264 | -------------------------------------------------------------------------------- /example/windows/runner/win32_window.cpp: -------------------------------------------------------------------------------- 1 | #include "win32_window.h" 2 | 3 | #include 4 | 5 | #include "resource.h" 6 | 7 | namespace { 8 | 9 | constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; 10 | 11 | // The number of Win32Window objects that currently exist. 12 | static int g_active_window_count = 0; 13 | 14 | using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); 15 | 16 | // Scale helper to convert logical scaler values to physical using passed in 17 | // scale factor 18 | int Scale(int source, double scale_factor) { 19 | return static_cast(source * scale_factor); 20 | } 21 | 22 | // Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. 23 | // This API is only needed for PerMonitor V1 awareness mode. 24 | void EnableFullDpiSupportIfAvailable(HWND hwnd) { 25 | HMODULE user32_module = LoadLibraryA("User32.dll"); 26 | if (!user32_module) { 27 | return; 28 | } 29 | auto enable_non_client_dpi_scaling = 30 | reinterpret_cast( 31 | GetProcAddress(user32_module, "EnableNonClientDpiScaling")); 32 | if (enable_non_client_dpi_scaling != nullptr) { 33 | enable_non_client_dpi_scaling(hwnd); 34 | FreeLibrary(user32_module); 35 | } 36 | } 37 | 38 | } // namespace 39 | 40 | // Manages the Win32Window's window class registration. 41 | class WindowClassRegistrar { 42 | public: 43 | ~WindowClassRegistrar() = default; 44 | 45 | // Returns the singleton registar instance. 46 | static WindowClassRegistrar* GetInstance() { 47 | if (!instance_) { 48 | instance_ = new WindowClassRegistrar(); 49 | } 50 | return instance_; 51 | } 52 | 53 | // Returns the name of the window class, registering the class if it hasn't 54 | // previously been registered. 55 | const wchar_t* GetWindowClass(); 56 | 57 | // Unregisters the window class. Should only be called if there are no 58 | // instances of the window. 59 | void UnregisterWindowClass(); 60 | 61 | private: 62 | WindowClassRegistrar() = default; 63 | 64 | static WindowClassRegistrar* instance_; 65 | 66 | bool class_registered_ = false; 67 | }; 68 | 69 | WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; 70 | 71 | const wchar_t* WindowClassRegistrar::GetWindowClass() { 72 | if (!class_registered_) { 73 | WNDCLASS window_class{}; 74 | window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); 75 | window_class.lpszClassName = kWindowClassName; 76 | window_class.style = CS_HREDRAW | CS_VREDRAW; 77 | window_class.cbClsExtra = 0; 78 | window_class.cbWndExtra = 0; 79 | window_class.hInstance = GetModuleHandle(nullptr); 80 | window_class.hIcon = 81 | LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); 82 | window_class.hbrBackground = 0; 83 | window_class.lpszMenuName = nullptr; 84 | window_class.lpfnWndProc = Win32Window::WndProc; 85 | RegisterClass(&window_class); 86 | class_registered_ = true; 87 | } 88 | return kWindowClassName; 89 | } 90 | 91 | void WindowClassRegistrar::UnregisterWindowClass() { 92 | UnregisterClass(kWindowClassName, nullptr); 93 | class_registered_ = false; 94 | } 95 | 96 | Win32Window::Win32Window() { 97 | ++g_active_window_count; 98 | } 99 | 100 | Win32Window::~Win32Window() { 101 | --g_active_window_count; 102 | Destroy(); 103 | } 104 | 105 | bool Win32Window::CreateAndShow(const std::wstring& title, 106 | const Point& origin, 107 | const Size& size) { 108 | Destroy(); 109 | 110 | const wchar_t* window_class = 111 | WindowClassRegistrar::GetInstance()->GetWindowClass(); 112 | 113 | const POINT target_point = {static_cast(origin.x), 114 | static_cast(origin.y)}; 115 | HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); 116 | UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); 117 | double scale_factor = dpi / 96.0; 118 | 119 | HWND window = CreateWindow( 120 | window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 121 | Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), 122 | Scale(size.width, scale_factor), Scale(size.height, scale_factor), 123 | nullptr, nullptr, GetModuleHandle(nullptr), this); 124 | 125 | if (!window) { 126 | return false; 127 | } 128 | 129 | return OnCreate(); 130 | } 131 | 132 | // static 133 | LRESULT CALLBACK Win32Window::WndProc(HWND const window, 134 | UINT const message, 135 | WPARAM const wparam, 136 | LPARAM const lparam) noexcept { 137 | if (message == WM_NCCREATE) { 138 | auto window_struct = reinterpret_cast(lparam); 139 | SetWindowLongPtr(window, GWLP_USERDATA, 140 | reinterpret_cast(window_struct->lpCreateParams)); 141 | 142 | auto that = static_cast(window_struct->lpCreateParams); 143 | EnableFullDpiSupportIfAvailable(window); 144 | that->window_handle_ = window; 145 | } else if (Win32Window* that = GetThisFromHandle(window)) { 146 | return that->MessageHandler(window, message, wparam, lparam); 147 | } 148 | 149 | return DefWindowProc(window, message, wparam, lparam); 150 | } 151 | 152 | LRESULT 153 | Win32Window::MessageHandler(HWND hwnd, 154 | UINT const message, 155 | WPARAM const wparam, 156 | LPARAM const lparam) noexcept { 157 | switch (message) { 158 | case WM_DESTROY: 159 | window_handle_ = nullptr; 160 | Destroy(); 161 | if (quit_on_close_) { 162 | PostQuitMessage(0); 163 | } 164 | return 0; 165 | 166 | case WM_DPICHANGED: { 167 | auto newRectSize = reinterpret_cast(lparam); 168 | LONG newWidth = newRectSize->right - newRectSize->left; 169 | LONG newHeight = newRectSize->bottom - newRectSize->top; 170 | 171 | SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, 172 | newHeight, SWP_NOZORDER | SWP_NOACTIVATE); 173 | 174 | return 0; 175 | } 176 | case WM_SIZE: { 177 | RECT rect = GetClientArea(); 178 | if (child_content_ != nullptr) { 179 | // Size and position the child window. 180 | MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, 181 | rect.bottom - rect.top, TRUE); 182 | } 183 | return 0; 184 | } 185 | 186 | case WM_ACTIVATE: 187 | if (child_content_ != nullptr) { 188 | SetFocus(child_content_); 189 | } 190 | return 0; 191 | } 192 | 193 | return DefWindowProc(window_handle_, message, wparam, lparam); 194 | } 195 | 196 | void Win32Window::Destroy() { 197 | OnDestroy(); 198 | 199 | if (window_handle_) { 200 | DestroyWindow(window_handle_); 201 | window_handle_ = nullptr; 202 | } 203 | if (g_active_window_count == 0) { 204 | WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); 205 | } 206 | } 207 | 208 | Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { 209 | return reinterpret_cast( 210 | GetWindowLongPtr(window, GWLP_USERDATA)); 211 | } 212 | 213 | void Win32Window::SetChildContent(HWND content) { 214 | child_content_ = content; 215 | SetParent(content, window_handle_); 216 | RECT frame = GetClientArea(); 217 | 218 | MoveWindow(content, frame.left, frame.top, frame.right - frame.left, 219 | frame.bottom - frame.top, true); 220 | 221 | SetFocus(child_content_); 222 | } 223 | 224 | RECT Win32Window::GetClientArea() { 225 | RECT frame; 226 | GetClientRect(window_handle_, &frame); 227 | return frame; 228 | } 229 | 230 | HWND Win32Window::GetHandle() { 231 | return window_handle_; 232 | } 233 | 234 | void Win32Window::SetQuitOnClose(bool quit_on_close) { 235 | quit_on_close_ = quit_on_close; 236 | } 237 | 238 | bool Win32Window::OnCreate() { 239 | // No-op; provided for subclasses. 240 | return true; 241 | } 242 | 243 | void Win32Window::OnDestroy() { 244 | // No-op; provided for subclasses. 245 | } 246 | -------------------------------------------------------------------------------- /lib/src/helper/matrix4_transform.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:flutter/foundation.dart'; 3 | import 'package:flutter/rendering.dart'; 4 | 5 | // @Copy from 6 | // Developed by Marcelo Glasberg (Aug 2019). 7 | // For more info, see: https://pub.dartlang.org/packages/matrix4_transform 8 | 9 | /// Helper class for easily creating Matrix4 transformations, 10 | /// that you can use in Container's `transform` parameter, 11 | /// and elsewhere. 12 | @immutable 13 | class Matrix4Transform { 14 | Matrix4Transform() : m = Matrix4.identity(); 15 | 16 | Matrix4Transform.from(Matrix4 m) : m = m.clone(); 17 | 18 | const Matrix4Transform._(this.m); 19 | 20 | Matrix4 get matrix4 => m.clone(); 21 | 22 | final Matrix4 m; 23 | 24 | /// Rotates by [angleRadians] radians, clockwise. 25 | /// If you define an origin it will have that point as the axis of rotation. 26 | Matrix4Transform rotate(double angleRadians, {Offset? origin}) { 27 | if (angleRadians == 0.0) { 28 | return this; 29 | } else if ((origin == null) || (origin.dx == 0.0 && origin.dy == 0.0)) { 30 | return Matrix4Transform._(m.clone()..rotateZ(angleRadians)); 31 | } else { 32 | return Matrix4Transform._(m.clone() 33 | ..translate(origin.dx, origin.dy) 34 | ..multiply(Matrix4.rotationZ(angleRadians)) 35 | ..translate(-origin.dx, -origin.dy)); 36 | } 37 | } 38 | 39 | /// Rotates by [angleDegrees] degrees (0 to 360 one turn), clockwise. 40 | /// If you define an origin it will have that point as the axis of rotation. 41 | Matrix4Transform rotateDegrees(double angleDegrees, {Offset? origin}) => 42 | rotate(_toRadians(angleDegrees), origin: origin); 43 | 44 | /// Rotates by [angleDegrees] degrees (0 to 360 one turn), clockwise. 45 | /// The axis of rotation will be the center of the object with the given size. 46 | Matrix4Transform rotateByCenterDegrees(double angleDegrees, Size size) => 47 | rotateByCenter(_toRadians(angleDegrees), size); 48 | 49 | /// Rotates by [angleRadians] radians, clockwise. 50 | /// The axis of rotation will be the center of the object with the given size. 51 | Matrix4Transform rotateByCenter(double angleRadians, Size size) => rotate( 52 | angleRadians, 53 | origin: Offset(size.width / 2, size.height / 2), 54 | ); 55 | 56 | /// Translates by [x] pixels (horizontal) and [y] pixels (vertical). 57 | /// Positive goes down/right. 58 | /// 59 | Matrix4Transform translate({double x = 0, double y = 0}) { 60 | return (x == 0 && y == 0) // 61 | ? this 62 | : Matrix4Transform._(m.clone()..leftTranslate(x, y)); 63 | } 64 | 65 | /// Translates by [x] pixels (horizontal) and [y] pixels (vertical), but in 66 | /// respect to the original coordinate system, before the translates/scales. 67 | /// 68 | /// Example: If you rotate 30 degrees, and then call this method to translate 69 | /// x:10 it will translate by a distance of 10 pixels in 30 degrees. 70 | /// 71 | /// Example: If you resize if by 1.5, and then call this method to translate 72 | /// x:10 it will translate by 15 pixels. 73 | /// 74 | Matrix4Transform translateOriginalCoordinates({ 75 | double x = 0, 76 | double y = 0, 77 | }) { 78 | return (x == 0 && y == 0) // 79 | ? this 80 | : Matrix4Transform._(m.clone()..translate(x, y)); 81 | } 82 | 83 | /// Scales by [factor], keeping the aspect ratio. 84 | /// Gets bigger for >1. 85 | /// Smaller for <1. 86 | /// Same size for 1 (and passing null is the same as passing 1). 87 | /// No size for 0. 88 | /// Passing null is the same as passing 1. 89 | Matrix4Transform scale(double factor, {Offset? origin}) => 90 | scaleBy(x: factor, y: factor, origin: origin); 91 | 92 | /// Scales by a factor of [x] (horizontal) and [y] (vertical). 93 | /// Gets bigger for >1. 94 | /// Smaller for <1. 95 | /// Same size for 1 (and passing null is the same as passing 1). 96 | /// No size for 0. 97 | Matrix4Transform scaleBy({double x = 1, double y = 1, Offset? origin}) { 98 | if (x == 1 && y == 1) { 99 | return this; 100 | } else if ((origin == null) || (origin.dx == 0.0 && origin.dy == 0.0)) { 101 | return Matrix4Transform._(// 102 | m.clone()..multiply(Matrix4.identity()..scale(x, y))); 103 | } else { 104 | return Matrix4Transform._(// 105 | m.clone() 106 | ..translate(origin.dx, origin.dy) 107 | ..multiply(Matrix4.identity()..scale(x, y)) 108 | ..translate(-origin.dx, -origin.dy)); 109 | } 110 | } 111 | 112 | /// Scales by [factor] horizontally. Keeps the same vertical scale. 113 | /// Gets bigger for >1. 114 | /// Smaller for <1. 115 | /// Same size for 1 (and passing null is the same as passing 1). 116 | /// No size for 0. 117 | Matrix4Transform scaleHorizontally(double factor, {Offset? origin}) => 118 | scaleBy(x: factor, origin: origin); 119 | 120 | /// Scales by [factor] vertically. Keeps the same horizontal scale. 121 | /// Gets bigger for >1. 122 | /// Smaller for <1. 123 | /// Same size for 1 (and passing null is the same as passing 1). 124 | /// No size for 0. 125 | Matrix4Transform scaleVertically(double factor, {Offset? origin}) => 126 | scaleBy(y: factor, origin: origin); 127 | 128 | /// Translates by [x] pixels (horizontal) and [y] pixels (vertical). 129 | /// Positive goes down/right. 130 | Matrix4Transform translateOffset(Offset offset) => 131 | Matrix4Transform._(m.clone()..translate(offset.dx, offset.dy)); 132 | 133 | /// Translates up by [distance] pixels. 134 | Matrix4Transform up(double distance) => translate(y: -distance); 135 | 136 | /// Translates down by [distance] pixels. 137 | Matrix4Transform down(double distance) => translate(y: distance); 138 | 139 | /// Translates right by [distance] pixels. 140 | Matrix4Transform right(double distance) => translate(x: distance); 141 | 142 | /// Translates up left [distance] pixels. 143 | Matrix4Transform left(double distance) => translate(x: -distance); 144 | 145 | /// Translates by [distance] pixels to the [direction]. 146 | /// The direction is in radians clockwise from the positive x-axis. 147 | Matrix4Transform direction(double directionRadians, double distance) => 148 | translateOffset(Offset.fromDirection(directionRadians, distance)); 149 | 150 | /// Translates by [distance] pixels to the [direction]. 151 | /// The direction is in degrees (0 to 360 one turn) clockwise from the positive x-axis. 152 | Matrix4Transform directionDegrees( 153 | double directionDegrees, 154 | double distance, 155 | ) => 156 | translateOffset( 157 | Offset.fromDirection( 158 | _toRadians(directionDegrees), 159 | distance, 160 | ), 161 | ); 162 | 163 | /// Translates up and right by [distance] pixels of distance. 164 | Matrix4Transform upRight(double distance) => // 165 | direction(-pi / 4, distance); 166 | 167 | /// Translates up and left [distance] pixels. 168 | Matrix4Transform upLeft(double distance) => // 169 | direction(-pi * 3 / 4, distance); 170 | 171 | /// Translates down and right by [distance] pixels. 172 | Matrix4Transform downRight(double distance) => // 173 | direction(pi / 4, distance); 174 | 175 | /// Translates down and left by [distance] pixels. 176 | Matrix4Transform downLeft(double distance) => // 177 | direction(pi * 3 / 4, distance); 178 | 179 | Matrix4Transform flipDiagonally({Offset? origin}) => // 180 | _flipDegrees(horizontal: 180, vertical: 180, origin: origin); 181 | 182 | Matrix4Transform flipHorizontally({Offset? origin}) => // 183 | _flipDegrees(horizontal: 180, origin: origin); 184 | 185 | Matrix4Transform flipVertically({Offset? origin}) => // 186 | _flipDegrees(vertical: 180, origin: origin); 187 | 188 | Matrix4Transform _flip({ 189 | double horizontal = 0.0, 190 | double vertical = 0.0, 191 | Offset? origin, 192 | }) { 193 | if ((horizontal == 0.0) && (vertical == 0.0)) { 194 | return this; 195 | } else if ((origin == null) || (origin.dx == 0.0 && origin.dy == 0.0)) { 196 | return Matrix4Transform._(m.clone() 197 | ..rotateY(horizontal) 198 | ..rotateX(vertical)); 199 | } else { 200 | return Matrix4Transform._(m.clone() 201 | ..translate(origin.dx, origin.dy) 202 | ..multiply(Matrix4.rotationY(horizontal)) 203 | ..multiply(Matrix4.rotationX(vertical)) 204 | ..translate(-origin.dx, -origin.dy)); 205 | } 206 | } 207 | 208 | /// Flips (with perspective) horizontally and vertically by [distance] pixels. 209 | Matrix4Transform _flipDegrees({ 210 | double horizontal = 0.0, 211 | double vertical = 0.0, 212 | Offset? origin, 213 | }) { 214 | return _flip( 215 | horizontal: _toRadians(horizontal), 216 | vertical: _toRadians(vertical), 217 | origin: origin, 218 | ); 219 | } 220 | 221 | double _toRadians(double angleDegrees) => angleDegrees * pi / 180; 222 | } 223 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Specify analysis options. 2 | # 3 | # Until there are meta linter rules, each desired lint must be explicitly enabled. 4 | # See: https://github.com/dart-lang/linter/issues/288 5 | # 6 | # For a list of lints, see: http://dart-lang.github.io/linter/lints/ 7 | # See the configuration guide for more 8 | # https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer 9 | # 10 | # There are other similar analysis options files in the flutter repos, 11 | # which should be kept in sync with this file: 12 | # 13 | # - analysis_options.yaml (this file) 14 | # - packages/flutter/lib/analysis_options_user.yaml 15 | # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml 16 | # - https://github.com/flutter/engine/blob/master/analysis_options.yaml 17 | # 18 | # This file contains the analysis options used by Flutter tools, such as IntelliJ, 19 | # Android Studio, and the `flutter analyze` command. 20 | 21 | analyzer: 22 | strong-mode: 23 | implicit-casts: false 24 | implicit-dynamic: false 25 | errors: 26 | # treat missing required parameters as a warning (not a hint) 27 | missing_required_param: warning 28 | # treat missing returns as a warning (not a hint) 29 | missing_return: warning 30 | # allow having TODOs in the code 31 | todo: ignore 32 | # allow self-reference to deprecated members (we do this because otherwise we have 33 | # to annotate every member in every test, assert, etc, when we deprecate something) 34 | deprecated_member_use_from_same_package: ignore 35 | # exclude: 36 | 37 | linter: 38 | rules: 39 | # these rules are documented on and in the same order as 40 | # the Dart Lint rules page to make maintenance easier 41 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml 42 | - always_declare_return_types 43 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 44 | - always_require_non_null_named_parameters 45 | - always_specify_types 46 | # - always_use_package_imports # we do this commonly 47 | - annotate_overrides 48 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types 49 | # - avoid_as # required for implicit-casts: true 50 | - avoid_bool_literals_in_conditional_expressions 51 | # - avoid_catches_without_on_clauses # we do this commonly 52 | # - avoid_catching_errors # we do this commonly 53 | - avoid_classes_with_only_static_members 54 | # - avoid_double_and_int_checks # only useful when targeting JS runtime 55 | - avoid_empty_else 56 | - avoid_equals_and_hash_code_on_mutable_classes 57 | # - avoid_escaping_inner_quotes # not yet tested 58 | - avoid_field_initializers_in_const_classes 59 | - avoid_function_literals_in_foreach_calls 60 | # - avoid_implementing_value_types # not yet tested 61 | - avoid_init_to_null 62 | # - avoid_js_rounded_ints # only useful when targeting JS runtime 63 | - avoid_null_checks_in_equality_operators 64 | # - avoid_positional_boolean_parameters # not yet tested 65 | # - avoid_print # not yet tested 66 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) 67 | # - avoid_redundant_argument_values # not yet tested 68 | - avoid_relative_lib_imports 69 | - avoid_renaming_method_parameters 70 | - avoid_return_types_on_setters 71 | # - avoid_returning_null # there are plenty of valid reasons to return null 72 | # - avoid_returning_null_for_future # not yet tested 73 | - avoid_returning_null_for_void 74 | # - avoid_returning_this # there are plenty of valid reasons to return this 75 | # - avoid_setters_without_getters # not yet tested 76 | - avoid_shadowing_type_parameters 77 | - avoid_single_cascade_in_expression_statements 78 | - avoid_slow_async_io 79 | # - avoid_type_to_string # we do this commonly 80 | - avoid_types_as_parameter_names 81 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types 82 | # - avoid_unnecessary_containers # not yet tested 83 | - avoid_unused_constructor_parameters 84 | - avoid_void_async 85 | # - avoid_web_libraries_in_flutter # not yet tested 86 | - await_only_futures 87 | - camel_case_extensions 88 | - camel_case_types 89 | - cancel_subscriptions 90 | # - cascade_invocations # not yet tested 91 | # - close_sinks # not reliable enough 92 | # - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 93 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 94 | - control_flow_in_finally 95 | # - curly_braces_in_flow_control_structures # not required by flutter style 96 | # - diagnostic_describe_all_properties # not yet tested 97 | - directives_ordering 98 | # - do_not_use_environment # we do this commonly 99 | - empty_catches 100 | - empty_constructor_bodies 101 | - empty_statements 102 | - exhaustive_cases 103 | # - file_names # not yet tested 104 | # - flutter_style_todos 105 | - hash_and_equals 106 | - implementation_imports 107 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 108 | - iterable_contains_unrelated_type 109 | # - join_return_with_assignment # not required by flutter style 110 | - leading_newlines_in_multiline_strings 111 | - library_names 112 | - library_prefixes 113 | # - lines_longer_than_80_chars # not required by flutter style 114 | - list_remove_unrelated_type 115 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 116 | # - missing_whitespace_between_adjacent_strings # not yet tested 117 | - no_adjacent_strings_in_list 118 | # - no_default_cases # too many false positives 119 | - no_duplicate_case_values 120 | - no_logic_in_create_state 121 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/ 122 | - non_constant_identifier_names 123 | # - null_closures # not required by flutter style 124 | # - omit_local_variable_types # opposite of always_specify_types 125 | # - one_member_abstracts # too many false positives 126 | # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 127 | - overridden_fields 128 | - package_api_docs 129 | # - package_names # non conforming packages in sdk 130 | - package_prefixed_library_names 131 | # - parameter_assignments # we do this commonly 132 | - prefer_adjacent_string_concatenation 133 | - prefer_asserts_in_initializer_lists 134 | # - prefer_asserts_with_message # not required by flutter style 135 | - prefer_collection_literals 136 | - prefer_conditional_assignment 137 | - prefer_const_constructors 138 | - prefer_const_constructors_in_immutables 139 | - prefer_const_declarations 140 | - prefer_const_literals_to_create_immutables 141 | # - prefer_constructors_over_static_methods # far too many false positives 142 | - prefer_contains 143 | # - prefer_double_quotes # opposite of prefer_single_quotes 144 | - prefer_equal_for_default_values 145 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods 146 | - prefer_final_fields 147 | - prefer_final_in_for_each 148 | - prefer_final_locals 149 | - prefer_for_elements_to_map_fromIterable 150 | - prefer_foreach 151 | # - prefer_function_declarations_over_variables # not yet tested 152 | - prefer_generic_function_type_aliases 153 | - prefer_if_elements_to_conditional_expressions 154 | - prefer_if_null_operators 155 | - prefer_initializing_formals 156 | - prefer_inlined_adds 157 | # - prefer_int_literals # not yet tested 158 | # - prefer_interpolation_to_compose_strings # not yet tested 159 | - prefer_is_empty 160 | - prefer_is_not_empty 161 | - prefer_is_not_operator 162 | - prefer_iterable_whereType 163 | # - prefer_mixin # https://github.com/dart-lang/language/issues/32 164 | # - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 165 | # - prefer_relative_imports # not yet tested 166 | - prefer_single_quotes 167 | - prefer_spread_collections 168 | - prefer_typing_uninitialized_variables 169 | - prefer_void_to_null 170 | # - provide_deprecation_message # not yet tested 171 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml 172 | - recursive_getters 173 | # - sized_box_for_whitespace # not yet tested 174 | - slash_for_doc_comments 175 | # - sort_child_properties_last # not yet tested 176 | - sort_constructors_first 177 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies 178 | - sort_unnamed_constructors_first 179 | - test_types_in_equals 180 | - throw_in_finally 181 | # - type_annotate_public_apis # subset of always_specify_types 182 | - type_init_formals 183 | # - unawaited_futures # too many false positives 184 | # - unnecessary_await_in_return # not yet tested 185 | - unnecessary_brace_in_string_interps 186 | - unnecessary_const 187 | # - unnecessary_final # conflicts with prefer_final_locals 188 | - unnecessary_getters_setters 189 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 190 | - unnecessary_new 191 | - unnecessary_null_aware_assignments 192 | # - unnecessary_null_checks # not yet tested 193 | - unnecessary_null_in_if_null_operators 194 | - unnecessary_nullable_for_final_variable_declarations 195 | - unnecessary_overrides 196 | - unnecessary_parenthesis 197 | # - unnecessary_raw_strings # not yet tested 198 | - unnecessary_statements 199 | - unnecessary_string_escapes 200 | - unnecessary_string_interpolations 201 | - unnecessary_this 202 | - unrelated_type_equality_checks 203 | # - unsafe_html # not yet tested 204 | - use_full_hex_values_for_flutter_colors 205 | # - use_function_type_syntax_for_parameters # not yet tested 206 | - use_is_even_rather_than_modulo 207 | # - use_key_in_widget_constructors # not yet tested 208 | - use_late_for_private_fields_and_variables 209 | - use_raw_strings 210 | - use_rethrow_when_possible 211 | # - use_setters_to_change_properties # not yet tested 212 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 213 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review 214 | - valid_regexps 215 | - void_checks -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Specify analysis options. 2 | # 3 | # For a list of lints, see: https://dart.dev/tools/linter-rules 4 | # For guidelines on configuring static analysis, see: 5 | # https://dart.dev/tools/analysis 6 | # 7 | # There are other similar analysis options files in the flutter repos, 8 | # which should be kept in sync with this file: 9 | # 10 | # - analysis_options.yaml (this file) 11 | # - https://github.com/flutter/packages/blob/main/analysis_options.yaml 12 | # 13 | # This file contains the analysis options used for code in the flutter/flutter 14 | # repository. 15 | 16 | analyzer: 17 | language: 18 | strict-casts: true 19 | strict-inference: true 20 | strict-raw-types: true 21 | errors: 22 | # allow deprecated members (we do this because otherwise we have to annotate 23 | # every member in every test, assert, etc, when we or the Dart SDK deprecates 24 | # something (https://github.com/flutter/flutter/issues/143312) 25 | deprecated_member_use: ignore 26 | deprecated_member_use_from_same_package: ignore 27 | exclude: 28 | - "bin/cache/**" 29 | # Ignore protoc generated files 30 | - "dev/conductor/lib/proto/*" 31 | - "engine/**" 32 | 33 | formatter: 34 | page_width: 100 35 | 36 | linter: 37 | rules: 38 | # This list is derived from the list of all available lints located at 39 | # https://github.com/dart-lang/sdk/blob/main/pkg/linter/example/all.yaml 40 | - always_declare_return_types 41 | # - always_put_control_body_on_new_line 42 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 43 | - always_specify_types 44 | # - always_use_package_imports # we do this commonly 45 | - annotate_overrides 46 | - annotate_redeclares 47 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types 48 | - avoid_bool_literals_in_conditional_expressions 49 | # - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023 50 | # - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/4998 51 | # - avoid_classes_with_only_static_members # we do this commonly for `abstract final class`es 52 | - avoid_double_and_int_checks 53 | - avoid_dynamic_calls 54 | - avoid_empty_else 55 | - avoid_equals_and_hash_code_on_mutable_classes 56 | - avoid_escaping_inner_quotes 57 | - avoid_field_initializers_in_const_classes 58 | # - avoid_final_parameters # incompatible with prefer_final_parameters 59 | - avoid_function_literals_in_foreach_calls 60 | # - avoid_futureor_void # not yet tested 61 | # - avoid_implementing_value_types # see https://github.com/dart-lang/linter/issues/4558 62 | - avoid_init_to_null 63 | - avoid_js_rounded_ints 64 | # - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to 65 | - avoid_null_checks_in_equality_operators 66 | # - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it 67 | - avoid_print 68 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) 69 | - avoid_redundant_argument_values 70 | - avoid_relative_lib_imports 71 | - avoid_renaming_method_parameters 72 | - avoid_return_types_on_setters 73 | - avoid_returning_null_for_void 74 | # - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives 75 | - avoid_setters_without_getters 76 | - avoid_shadowing_type_parameters 77 | - avoid_single_cascade_in_expression_statements 78 | - avoid_slow_async_io 79 | - avoid_type_to_string 80 | - avoid_types_as_parameter_names 81 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types 82 | - avoid_unnecessary_containers 83 | - avoid_unused_constructor_parameters 84 | - avoid_void_async 85 | # - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere 86 | - await_only_futures 87 | - camel_case_extensions 88 | - camel_case_types 89 | - cancel_subscriptions 90 | # - cascade_invocations # doesn't match the typical style of this repo 91 | - cast_nullable_to_non_nullable 92 | # - close_sinks # not reliable enough 93 | - collection_methods_unrelated_type 94 | - combinators_ordering 95 | # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142 96 | - conditional_uri_does_not_exist 97 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 98 | - control_flow_in_finally 99 | - curly_braces_in_flow_control_structures 100 | - dangling_library_doc_comments 101 | - depend_on_referenced_packages 102 | - deprecated_consistency 103 | # - deprecated_member_use_from_same_package # we allow self-references to deprecated members 104 | # - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib) 105 | - directives_ordering 106 | # - discarded_futures # too many false positives, similar to unawaited_futures 107 | # - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic 108 | # - document_ignores # not yet tested 109 | - empty_catches 110 | - empty_constructor_bodies 111 | - empty_statements 112 | - eol_at_end_of_file 113 | - exhaustive_cases 114 | - file_names 115 | - flutter_style_todos 116 | - hash_and_equals 117 | - implementation_imports 118 | - implicit_call_tearoffs 119 | - implicit_reopen 120 | - invalid_case_patterns 121 | - invalid_runtime_check_with_js_interop_types 122 | # - join_return_with_assignment # not required by flutter style 123 | - leading_newlines_in_multiline_strings 124 | - library_annotations 125 | - library_names 126 | - library_prefixes 127 | - library_private_types_in_public_api 128 | # - lines_longer_than_80_chars # not required by flutter style 129 | - literal_only_boolean_expressions 130 | # - matching_super_parameters # blocked on https://github.com/dart-lang/language/issues/2509 131 | - missing_code_block_language_in_doc_comment 132 | - missing_whitespace_between_adjacent_strings 133 | - no_adjacent_strings_in_list 134 | - no_default_cases 135 | - no_duplicate_case_values 136 | - no_leading_underscores_for_library_prefixes 137 | - no_leading_underscores_for_local_identifiers 138 | - no_literal_bool_comparisons 139 | - no_logic_in_create_state 140 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/ 141 | - no_self_assignments 142 | - no_wildcard_variable_uses 143 | - non_constant_identifier_names 144 | - noop_primitive_operations 145 | - null_check_on_nullable_type_parameter 146 | - null_closures 147 | # - omit_local_variable_types # opposite of always_specify_types 148 | # - omit_obvious_local_variable_types # not yet tested 149 | # - omit_obvious_property_types # not yet tested 150 | # - one_member_abstracts # too many false positives 151 | - only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al 152 | - overridden_fields 153 | - package_names 154 | - package_prefixed_library_names 155 | # - parameter_assignments # we do this commonly 156 | - prefer_adjacent_string_concatenation 157 | - prefer_asserts_in_initializer_lists 158 | # - prefer_asserts_with_message # not required by flutter style 159 | - prefer_collection_literals 160 | - prefer_conditional_assignment 161 | - prefer_const_constructors 162 | - prefer_const_constructors_in_immutables 163 | - prefer_const_declarations 164 | - prefer_const_literals_to_create_immutables 165 | # - prefer_constructors_over_static_methods # far too many false positives 166 | - prefer_contains 167 | # - prefer_double_quotes # opposite of prefer_single_quotes 168 | # - prefer_expression_function_bodies # conflicts with ./docs/contributing/Style-guide-for-Flutter-repo.md#consider-using--for-short-functions-and-methods 169 | - prefer_final_fields 170 | - prefer_final_in_for_each 171 | - prefer_final_locals 172 | # - prefer_final_parameters # adds too much verbosity 173 | - prefer_for_elements_to_map_fromIterable 174 | - prefer_foreach 175 | - prefer_function_declarations_over_variables 176 | - prefer_generic_function_type_aliases 177 | - prefer_if_elements_to_conditional_expressions 178 | - prefer_if_null_operators 179 | - prefer_initializing_formals 180 | - prefer_inlined_adds 181 | # - prefer_int_literals # conflicts with ./docs/contributing/Style-guide-for-Flutter-repo.md#use-double-literals-for-double-constants 182 | - prefer_interpolation_to_compose_strings 183 | - prefer_is_empty 184 | - prefer_is_not_empty 185 | - prefer_is_not_operator 186 | - prefer_iterable_whereType 187 | - prefer_mixin 188 | # - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere 189 | - prefer_null_aware_operators 190 | - prefer_relative_imports 191 | - prefer_single_quotes 192 | - prefer_spread_collections 193 | - prefer_typing_uninitialized_variables 194 | - prefer_void_to_null 195 | - provide_deprecation_message 196 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml 197 | - recursive_getters 198 | # - require_trailing_commas # would be nice, but requires a lot of manual work: 10,000+ code locations would need to be reformatted by hand after bulk fix is applied 199 | - secure_pubspec_urls 200 | - sized_box_for_whitespace 201 | - sized_box_shrink_expand 202 | - slash_for_doc_comments 203 | - sort_child_properties_last 204 | - sort_constructors_first 205 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies 206 | - sort_unnamed_constructors_first 207 | # - specify_nonobvious_local_variable_types # not yet tested 208 | # - specify_nonobvious_property_types # not yet tested 209 | - strict_top_level_inference 210 | - test_types_in_equals 211 | - throw_in_finally 212 | - tighten_type_of_initializing_formals 213 | # - type_annotate_public_apis # subset of always_specify_types 214 | - type_init_formals 215 | - type_literal_in_constant_pattern 216 | # - unawaited_futures # too many false positives, especially with the way AnimationController works 217 | # - unintended_html_in_doc_comment # blocked on https://github.com/dart-lang/linter/issues/5065 218 | # - unnecessary_async # not yet tested 219 | - unnecessary_await_in_return 220 | - unnecessary_brace_in_string_interps 221 | - unnecessary_breaks 222 | - unnecessary_const 223 | - unnecessary_constructor_name 224 | # - unnecessary_final # conflicts with prefer_final_locals 225 | - unnecessary_getters_setters 226 | # - unnecessary_ignore # Disabled by default to simplify migrations; should be periodically enabled locally to clean up offenders 227 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 228 | - unnecessary_late 229 | - unnecessary_library_directive 230 | # - unnecessary_library_name # blocked on https://github.com/dart-lang/dartdoc/issues/3882 231 | - unnecessary_new 232 | - unnecessary_null_aware_assignments 233 | - unnecessary_null_aware_operator_on_extension_on_nullable 234 | - unnecessary_null_checks 235 | - unnecessary_null_in_if_null_operators 236 | - unnecessary_nullable_for_final_variable_declarations 237 | - unnecessary_overrides 238 | - unnecessary_parenthesis 239 | # - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint 240 | - unnecessary_statements 241 | - unnecessary_string_escapes 242 | - unnecessary_string_interpolations 243 | - unnecessary_this 244 | - unnecessary_to_list_in_spreads 245 | - unnecessary_underscores 246 | - unreachable_from_main 247 | - unrelated_type_equality_checks 248 | # - unsafe_variance # not yet tested 249 | - use_build_context_synchronously 250 | - use_colored_box 251 | # - use_decorated_box # leads to bugs: DecoratedBox and Container are not equivalent (Container inserts extra padding) 252 | - use_enums 253 | - use_full_hex_values_for_flutter_colors 254 | - use_function_type_syntax_for_parameters 255 | - use_if_null_to_convert_nulls_to_bools 256 | - use_is_even_rather_than_modulo 257 | - use_key_in_widget_constructors 258 | - use_late_for_private_fields_and_variables 259 | - use_named_constants 260 | - use_raw_strings 261 | - use_rethrow_when_possible 262 | - use_setters_to_change_properties 263 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 264 | - use_string_in_part_of_directives 265 | - use_super_parameters 266 | - use_test_throws_matchers 267 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review 268 | - use_truncating_division 269 | - valid_regexps 270 | - void_checks 271 | --------------------------------------------------------------------------------