├── .gitignore ├── .metadata ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── toly1994 │ │ │ │ └── ianim │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── 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 │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ └── values │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── font │ └── CHOPS.TTF └── images │ ├── icon_8.jpg │ ├── icon_head.jpg │ ├── icon_head.png │ └── wy_300x200.jpg ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── 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-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── 14 │ └── debug │ │ ├── circle_anim.dart │ │ └── main.dart ├── 01_text │ ├── 01_color │ │ ├── 01_static │ │ │ ├── color_text.dart │ │ │ └── main.dart │ │ └── 02_anim │ │ │ ├── color_text.dart │ │ │ └── main.dart │ ├── 02_skew_shadow │ │ ├── 01_static │ │ │ ├── main.dart │ │ │ └── skew_show_text.dart │ │ └── 02_anim │ │ │ ├── main.dart │ │ │ └── skew_show_text.dart │ └── 03_typer │ │ ├── 01_timer_test │ │ └── timer_test.dart │ │ └── 02_anim │ │ ├── main.dart │ │ └── text_typer.dart ├── 02 │ ├── 01_attr │ │ ├── 01_value_duration │ │ │ ├── circle_anim.dart │ │ │ └── main.dart │ │ └── 02_bound │ │ │ ├── circle_anim.dart │ │ │ └── main.dart │ ├── 02_function │ │ ├── 01_forward │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ └── point_data.dart │ │ ├── 02_reverse │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ └── point_data.dart │ │ ├── 03_repeat │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ └── point_data.dart │ │ ├── 04_stop │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ └── point_data.dart │ │ ├── 05_fling │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ └── point_data.dart │ │ └── 06_fling_spring │ │ │ ├── anim_painter.dart │ │ │ ├── anim_panel.dart │ │ │ ├── main.dart │ │ │ ├── point_data.dart │ │ │ └── spring_painter.dart │ └── 03_status │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart ├── 03_curve │ ├── 01 │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart │ ├── 02 │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart │ ├── 03 │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart │ └── 04 │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ ├── point_data.dart │ │ └── toly_curve.dart ├── 04_tween │ ├── 01_color │ │ ├── circle_anim.dart │ │ └── main.dart │ ├── 02_color_tween │ │ ├── circle_anim.dart │ │ └── main.dart │ ├── 03_tween_evaluate │ │ ├── circle_anim.dart │ │ └── main.dart │ ├── 04_animate │ │ ├── circle_anim.dart │ │ └── main.dart │ ├── 05_curve_tween │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart │ ├── 06_tween_sequence │ │ ├── anim_painter.dart │ │ ├── anim_panel.dart │ │ ├── main.dart │ │ └── point_data.dart │ ├── 07_text_style_tween │ │ ├── circle.dart │ │ ├── circle_anim.dart │ │ └── main.dart │ └── 08_circle_color_tween │ │ ├── circle.dart │ │ ├── circle_anim.dart │ │ └── main.dart ├── 05_simple │ ├── 01_shine_static │ │ ├── circle_shine_image.dart │ │ └── main.dart │ ├── 02_shine_anim │ │ ├── circle_shine_image.dart │ │ └── main.dart │ ├── 03_toggle_rotate │ │ ├── main.dart │ │ └── toggle_rotate.dart │ ├── 04_compare │ │ ├── main.dart │ │ └── toggle_rotate.dart │ ├── 05_burst_static │ │ ├── burst_menu.dart │ │ └── main.dart │ ├── 06_burst_static_angle │ │ ├── burst_menu.dart │ │ └── main.dart │ ├── 07_burst_anim_01 │ │ ├── burst_menu.dart │ │ └── main.dart │ └── 08_burst_anim_last │ │ ├── burst_menu.dart │ │ └── main.dart ├── 06_loading │ ├── 01_halo_circle │ │ ├── 01_circle_static │ │ │ ├── circle_halo.dart │ │ │ └── main.dart │ │ ├── 02_light_static │ │ │ ├── circle_halo.dart │ │ │ └── main.dart │ │ ├── 03_circle_anim │ │ │ ├── circle_halo.dart │ │ │ └── main.dart │ │ ├── 04_light_anim │ │ │ ├── circle_halo.dart │ │ │ └── main.dart │ │ └── 05_circle_halo_last │ │ │ ├── circle_halo.dart │ │ │ └── main.dart │ ├── 02_rotate │ │ ├── 01_static │ │ │ ├── main.dart │ │ │ └── rotate_loading.dart │ │ ├── 02_anim_01 │ │ │ ├── main.dart │ │ │ └── rotate_loading.dart │ │ └── 03_anim_last │ │ │ ├── main.dart │ │ │ └── rotate_loading.dart │ ├── 03_cross │ │ ├── 01_cross_single │ │ │ ├── cross_loading.dart │ │ │ └── main.dart │ │ ├── 02_cross_static │ │ │ ├── cross_loading.dart │ │ │ └── main.dart │ │ └── 03_cross_anim │ │ │ ├── cross_loading.dart │ │ │ └── main.dart │ └── 04_ovel │ │ ├── 01_oval_single │ │ ├── main.dart │ │ └── oval_loading.dart │ │ ├── 02_sin_single │ │ ├── main.dart │ │ └── oval_loading.dart │ │ └── 03_oval_last │ │ ├── main.dart │ │ └── oval_loading.dart ├── 07_animated_widget │ ├── 01_RotationTransition │ │ └── main.dart │ ├── 02_ScaleTransition │ │ └── main.dart │ ├── 03_SlideTransition │ │ └── main.dart │ ├── 04_AlignTransition │ │ └── main.dart │ └── 05_DecoratedBoxTransition │ │ └── main.dart ├── 09_implicitly_animated_widget │ ├── 01_AnimatedOpacity │ │ └── main.dart │ ├── 02_AnimatedDefaultTextStyle │ │ └── main.dart │ ├── 03_AnimatedAlign │ │ └── main.dart │ ├── 04_AnimatedContainer │ │ └── main.dart │ └── 05_TweenAnimationBuilder │ │ └── main.dart ├── 10_implicitly_debug │ └── main.dart ├── 11_other │ ├── 01_painter │ │ ├── 01_AnimatedIcon │ │ │ └── main.dart │ │ └── 02_CupertinoActivityIndicator │ │ │ └── main.dart │ ├── 02_other │ │ ├── 01_AnimatedCrossFade │ │ │ └── main.dart │ │ └── 02_AnimatedSwitcher │ │ │ └── main.dart │ └── 04_router │ │ ├── 01_common │ │ └── main.dart │ │ └── 02_anim │ │ └── main.dart ├── 15_ticker │ ├── ticker │ │ ├── main.dart │ │ └── ticker_demo.dart │ ├── ticker_muted │ │ ├── main.dart │ │ └── ticker_demo.dart │ └── ticker_provider │ │ ├── main.dart │ │ └── ticker_demo.dart └── 16_clock │ ├── 01 │ ├── clock_widget.dart │ └── main.dart │ ├── 02 │ ├── clock_widget.dart │ └── main.dart │ ├── 03 │ ├── clock_widget.dart │ └── main.dart │ ├── 04_stack │ ├── clock_widget.dart │ └── main.dart │ ├── 05_last │ ├── clock_widget.dart │ └── main.dart │ └── 06_lizi │ ├── 01 │ ├── clock_fx.dart │ ├── clock_widget.dart │ ├── main.dart │ ├── particle.dart │ ├── particle_clock_fx.dart │ └── utils │ │ └── rnd.dart │ ├── 02 │ ├── clock_fx.dart │ ├── clock_widget.dart │ ├── main.dart │ ├── particle.dart │ └── utils │ │ └── rnd.dart │ ├── 03 │ ├── clock_fx.dart │ ├── clock_widget.dart │ ├── main.dart │ ├── particle.dart │ └── utils │ │ └── rnd.dart │ └── 04 │ ├── clock_fx.dart │ ├── clock_widget.dart │ ├── main.dart │ ├── particle.dart │ └── utils │ └── rnd.dart ├── pubspec.lock └── pubspec.yaml /.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 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.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: 1d9032c7e1d867f071f2277eb1673e8f9b0274e3 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ianim 2 | 3 | A new Flutter application. 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 30 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | defaultConfig { 36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 37 | applicationId "com.toly1994.ianim" 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 | 57 | dependencies { 58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 59 | } 60 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 13 | 17 | 21 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/toly1994/ianim/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.toly1994.ianim 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.3.50' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.1.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /assets/font/CHOPS.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/assets/font/CHOPS.TTF -------------------------------------------------------------------------------- /assets/images/icon_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/assets/images/icon_8.jpg -------------------------------------------------------------------------------- /assets/images/icon_head.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/assets/images/icon_head.jpg -------------------------------------------------------------------------------- /assets/images/icon_head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/assets/images/icon_head.png -------------------------------------------------------------------------------- /assets/images/wy_300x200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/assets/images/wy_300x200.jpg -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/toly1994328/ianim/6a0ae1a16cda233c0df19191da5c3d8721381a30/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | ianim 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 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/01_text/01_color/01_static/color_text.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui' as ui; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | class AnimText extends StatelessWidget { 7 | final String text = "张风捷特烈"; 8 | 9 | final List colors = [ 10 | Color(0xFFF60C0C), 11 | Color(0xFFF3B913), 12 | Color(0xFFE7F716), 13 | Color(0xFF3DF30B), 14 | Color(0xFF0DF6EF), 15 | Color(0xFF0829FB), 16 | Color(0xFFB709F4), 17 | ]; 18 | 19 | final List pos = [ 20 | 1.0 / 7, 2.0 / 7, 3.0 / 7, 21 | 4.0 / 7, 5.0 / 7, 6.0 / 7, 1.0 ]; 22 | 23 | Paint getPaint() { 24 | Paint paint = Paint(); 25 | paint 26 | ..style = PaintingStyle.stroke 27 | ..strokeWidth = 2; 28 | paint.shader = ui.Gradient.linear( 29 | const Offset(0, 0), 30 | const Offset(100, 0), 31 | colors, 32 | pos, 33 | TileMode.mirror, 34 | Matrix4.rotationZ(pi / 6).storage, 35 | ); 36 | paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 10); 37 | return paint; 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return Text( 43 | text, 44 | style: TextStyle(fontSize: 60, foreground: getPaint()), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/01_text/01_color/01_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'color_text.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimText(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/01_text/01_color/02_anim/color_text.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui' as ui; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | class AnimText extends StatefulWidget { 7 | @override 8 | _AnimTextState createState() => _AnimTextState(); 9 | } 10 | 11 | class _AnimTextState extends State 12 | with SingleTickerProviderStateMixin { 13 | 14 | // 1.混入 mixin 15 | // 1. 声明动画器对象 16 | AnimationController _ctrl; 17 | 18 | final Duration animDuration = const Duration(milliseconds: 1000); // 动画时长 19 | 20 | @override 21 | void initState() { 22 | super.initState(); 23 | // 1. 声明动画器对象 24 | _ctrl = AnimationController(vsync: this, duration: animDuration); 25 | } 26 | 27 | final List colors = [ 28 | Color(0xFFF60C0C), 29 | Color(0xFFF3B913), 30 | Color(0xFFE7F716), 31 | Color(0xFF3DF30B), 32 | Color(0xFF0DF6EF), 33 | Color(0xFF0829FB), 34 | Color(0xFFB709F4), 35 | ]; 36 | 37 | final List pos = [ 38 | 1.0 / 7, 39 | 2.0 / 7, 40 | 3.0 / 7, 41 | 4.0 / 7, 42 | 5.0 / 7, 43 | 6.0 / 7, 44 | 1.0 45 | ]; 46 | 47 | Paint getPaint() { 48 | Paint paint = Paint() 49 | ..style = PaintingStyle.stroke 50 | ..strokeWidth = 2; 51 | paint.shader = ui.Gradient.linear( 52 | const Offset(0, 0), 53 | const Offset(100, 0), 54 | colors, 55 | pos, 56 | TileMode.mirror, 57 | Matrix4.rotationZ(pi / 6).storage, 58 | ); 59 | paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 15 * _ctrl.value); 60 | return paint; 61 | } 62 | 63 | 64 | 65 | @override 66 | void dispose() { 67 | // 2. 销毁动画器 68 | _ctrl.dispose(); 69 | super.dispose(); 70 | } 71 | 72 | @override 73 | Widget build(BuildContext context) { 74 | return GestureDetector( 75 | onTap: _startAnim, 76 | child: AnimatedBuilder( // 4.通过 AnimatedBuilder 监听动画器构建组件 77 | animation: _ctrl, 78 | builder: _buildByAnim, 79 | ), 80 | ); 81 | } 82 | 83 | Widget _buildByAnim(BuildContext context, Widget child) { 84 | return Text( 85 | "张风捷特烈", 86 | style: TextStyle(fontSize: 60, foreground: getPaint()), 87 | ); 88 | } 89 | 90 | void _startAnim() { 91 | // 3. 启动动画器 92 | _ctrl.forward(from: 0); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/01_text/01_color/02_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'color_text.dart'; 5 | 6 | void main() { 7 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 8 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 9 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 10 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: Scaffold( 24 | body: Center( 25 | // Center is a layout widget. It takes a single child and positions it 26 | // in the middle of the parent. 27 | child: AnimText(), 28 | ))); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/01_text/02_skew_shadow/01_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'skew_show_text.dart'; 5 | 6 | void main() { 7 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 8 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 9 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 10 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | title: 'Flutter Demo', 19 | debugShowCheckedModeBanner: false, 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: Scaffold( 24 | body: Center( 25 | child: SkewShadowText(), 26 | ))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/01_text/02_skew_shadow/01_static/skew_show_text.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class SkewShadowText extends StatelessWidget{ 6 | 7 | final TextStyle commonStyle = TextStyle(fontSize: 60, color: Colors.blue); 8 | final TextStyle shadowStyle = TextStyle(fontSize: 60, color: Colors.blue.withAlpha(88)); 9 | final String text = '张风捷特烈'; 10 | @override 11 | Widget build(BuildContext context) { 12 | Matrix4 matrix4 = Matrix4.skewX(4*pi/180); 13 | return Stack( 14 | children: [ 15 | Text( 16 | text, 17 | style: commonStyle, 18 | ), 19 | Transform( 20 | transform: matrix4, 21 | child: Text( 22 | text, 23 | style: shadowStyle, 24 | ), 25 | ), 26 | ], 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/01_text/02_skew_shadow/02_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'skew_show_text.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: SkewShadowText(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/01_text/02_skew_shadow/02_anim/skew_show_text.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class SkewShadowText extends StatefulWidget { 6 | @override 7 | _SkewShadowTextState createState() => _SkewShadowTextState(); 8 | } 9 | 10 | class _SkewShadowTextState extends State 11 | with SingleTickerProviderStateMixin { 12 | AnimationController _ctrl; 13 | 14 | final Duration animDuration = const Duration(milliseconds: 800); 15 | 16 | final TextStyle commonStyle = TextStyle(fontSize: 60, color: Colors.blue); 17 | final TextStyle shadowStyle = 18 | TextStyle(fontSize: 60, color: Colors.blue.withAlpha(88)); 19 | String text = "张风捷特烈"; 20 | 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | _ctrl = AnimationController(vsync: this, duration: animDuration); 26 | } 27 | 28 | @override 29 | void dispose() { 30 | _ctrl.dispose(); 31 | super.dispose(); 32 | } 33 | 34 | @override 35 | Widget build(BuildContext context) { 36 | return GestureDetector( 37 | onTap: _startAnim, 38 | child: Stack( 39 | children: [ 40 | Text(text, style: commonStyle,), 41 | AnimatedBuilder( 42 | animation: _ctrl, 43 | builder: _buildByAnim, 44 | ), 45 | ], 46 | )); 47 | } 48 | 49 | double get rad => 6 * (_ctrl.value) / 180 * pi; 50 | 51 | Widget _buildByAnim(_, __) => Transform( 52 | transform: Matrix4.skewX(rad), 53 | child: Text( 54 | text, 55 | style: shadowStyle, 56 | ), 57 | ); 58 | 59 | void _startAnim() { 60 | _ctrl.forward(from: 0); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/01_text/03_typer/01_timer_test/timer_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | int count = 0; 4 | 5 | main() { 6 | Timer.periodic(Duration(seconds: 1), _callback); 7 | } 8 | 9 | void _callback(Timer timer) { 10 | count++; 11 | print("------${DateTime.now().toIso8601String()}---------"); 12 | if (count >= 10) { 13 | timer.cancel(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/01_text/03_typer/02_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'text_typer.dart'; 5 | 6 | void main() { 7 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 8 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 9 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 10 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: Scaffold( 24 | body: Center( 25 | child: TextTyper(), 26 | ))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/01_text/03_typer/02_anim/text_typer.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class TextTyper extends StatefulWidget { 6 | @override 7 | _TextTyperState createState() => _TextTyperState(); 8 | } 9 | 10 | class _TextTyperState extends State { 11 | 12 | final Duration animDuration = const Duration(milliseconds: 200); 13 | 14 | final String text = '桃树、杏树、梨树,你不让我,我不让你,都开满了花赶趟儿。' 15 | '红的像火,粉的像霞,白的像雪。花里带着甜味,闭了眼,' 16 | '树上仿佛已经满是桃儿、杏儿、梨儿。'; 17 | 18 | final ValueNotifier data = ValueNotifier(""); 19 | 20 | Timer _timer; 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | _startAnim(); 26 | } 27 | 28 | int currentIndex = 0; 29 | 30 | String get currentText =>text.substring(0,currentIndex); 31 | 32 | void _type(Timer timer) { 33 | if (currentIndex < text.length) { 34 | currentIndex++; 35 | data.value= currentText; 36 | }else{ 37 | _timer?.cancel(); 38 | _timer=null; 39 | } 40 | } 41 | 42 | @override 43 | void dispose() { 44 | _timer?.cancel(); 45 | data.dispose(); 46 | super.dispose(); 47 | } 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return GestureDetector( 52 | onTap: _startAnim, 53 | child: SizedBox( 54 | width: 300, 55 | child: AnimatedBuilder( 56 | animation: data, 57 | builder: _buildByAnim, 58 | ), 59 | ), 60 | ); 61 | } 62 | 63 | Widget _buildByAnim(_, __) => Text( 64 | data.value, 65 | style: const TextStyle(color: Colors.blue), 66 | ); 67 | 68 | void _startAnim() { 69 | _timer?.cancel(); 70 | data.value = ''; 71 | currentIndex = 0; 72 | _timer = Timer.periodic(animDuration, _type); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/02/01_attr/01_value_duration/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds:2000); 13 | 14 | @override 15 | void initState() { 16 | super.initState(); 17 | _ctrl = AnimationController( 18 | value: 0.4, 19 | vsync: this, 20 | duration: animDuration, 21 | ); 22 | } 23 | 24 | @override 25 | void dispose() { 26 | _ctrl.dispose(); 27 | super.dispose(); 28 | } 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return GestureDetector( 33 | onTap: _startAnim, 34 | child: AnimatedBuilder( 35 | animation: _ctrl, 36 | builder: _buildByAnim, 37 | )); 38 | } 39 | 40 | double get radius => 80*_ctrl.value ; 41 | 42 | Widget _buildByAnim(_, __) => Container( 43 | width: radius * 2, 44 | height: radius * 2, 45 | decoration: 46 | BoxDecoration(color: Colors.blue, shape: BoxShape.circle), 47 | ); 48 | 49 | void _startAnim() { 50 | _ctrl.forward(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/02/01_attr/01_value_duration/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/01_attr/02_bound/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds:1000); 13 | 14 | @override 15 | void initState() { 16 | super.initState(); 17 | _ctrl = AnimationController( 18 | lowerBound: 32, 19 | upperBound: 80, 20 | vsync: this, 21 | duration: animDuration, 22 | ); 23 | } 24 | 25 | @override 26 | void dispose() { 27 | _ctrl.dispose(); 28 | super.dispose(); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return GestureDetector( 34 | onTap: _startAnim, 35 | child: AnimatedBuilder( 36 | animation: _ctrl, 37 | builder: _buildByAnim, 38 | )); 39 | } 40 | 41 | double get radius => _ctrl.value ; 42 | 43 | Widget _buildByAnim(_, __) => Container( 44 | width: radius * 2, 45 | height: radius * 2, 46 | decoration: 47 | BoxDecoration(color: Colors.blue, shape: BoxShape.circle), 48 | ); 49 | 50 | void _startAnim() { 51 | _ctrl.forward(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/02/01_attr/02_bound/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/01_forward/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | // Animation curve; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 31 | } 32 | 33 | @override 34 | void dispose() { 35 | _ctrl.dispose(); 36 | points.dispose(); 37 | super.dispose(); 38 | } 39 | 40 | void _collectPoint() { 41 | points.push(_ctrl.value); 42 | } 43 | 44 | void _startAnim() async{ 45 | points.clear(); 46 | print('start!---${DateTime.now().toIso8601String()}----------'); 47 | // await _ctrl.forward(from: 0); 48 | await _ctrl.forward(from: 0.4); 49 | print('done!---${DateTime.now().toIso8601String()}----------'); 50 | } 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return GestureDetector( 55 | onTap: _startAnim, 56 | child: CustomPaint( 57 | painter: AnimPainter(points), 58 | size: const Size( 59 | 200, 60 | 200, 61 | ), 62 | ), 63 | ); 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /lib/02/02_function/01_forward/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/01_forward/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/02_reverse/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | 16 | PointData points = PointData(); 17 | AnimationController _ctrl; 18 | final Duration animDuration = const Duration(milliseconds: 1000); 19 | 20 | @override 21 | void initState() { 22 | super.initState(); 23 | _ctrl = AnimationController( 24 | vsync: this, 25 | duration: animDuration, 26 | )..addListener(_collectPoint); 27 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 28 | } 29 | 30 | @override 31 | void dispose() { 32 | _ctrl.dispose(); 33 | points.dispose(); 34 | super.dispose(); 35 | } 36 | 37 | void _collectPoint() { 38 | points.push(_ctrl.value); 39 | } 40 | 41 | void _startAnim() async{ 42 | points.clear(); 43 | print('start!---${DateTime.now().toIso8601String()}----------'); 44 | await _ctrl.reverse(from: 1); 45 | print('done!---${DateTime.now().toIso8601String()}----------'); 46 | } 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return GestureDetector( 51 | onTap: _startAnim, 52 | child: CustomPaint( 53 | painter: AnimPainter(points), 54 | size: const Size( 55 | 200, 56 | 200, 57 | ), 58 | ), 59 | ); 60 | } 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /lib/02/02_function/02_reverse/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/02_reverse/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/03_repeat/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'anim_painter.dart'; 7 | import 'point_data.dart'; 8 | 9 | class AnimPanel extends StatefulWidget { 10 | @override 11 | _AnimPanelState createState() => _AnimPanelState(); 12 | } 13 | 14 | class _AnimPanelState extends State 15 | with SingleTickerProviderStateMixin { 16 | 17 | PointData points = PointData(); 18 | AnimationController _ctrl; 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | _ctrl = AnimationController( 25 | vsync: this, 26 | duration: animDuration, 27 | )..addListener(_collectPoint)..addStatusListener(_listenStatus); 28 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 29 | } 30 | 31 | @override 32 | void dispose() { 33 | _ctrl.dispose(); 34 | points.dispose(); 35 | super.dispose(); 36 | } 37 | 38 | void _collectPoint() { 39 | points.push(_ctrl.value); 40 | } 41 | 42 | void _listenStatus(AnimationStatus status){ 43 | // print(status); 44 | // if(status == AnimationStatus.reverse){ 45 | // points.clear(); 46 | // } 47 | } 48 | 49 | void _startAnim() async{ 50 | points.clear(); 51 | Timer(Duration(seconds: 4),_stop); 52 | print('start!---${DateTime.now().toIso8601String()}----------'); 53 | await _ctrl.repeat(reverse: true); 54 | print('done!---${DateTime.now().toIso8601String()}----------'); 55 | 56 | } 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return GestureDetector( 61 | onTap: _startAnim, 62 | child: CustomPaint( 63 | painter: AnimPainter(points), 64 | size: const Size( 65 | 600, 66 | 200, 67 | ), 68 | ), 69 | ); 70 | } 71 | 72 | void _stop() { 73 | _ctrl.stop(); 74 | } 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /lib/02/02_function/03_repeat/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/03_repeat/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/04_stop/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | import 'anim_painter.dart'; 7 | import 'point_data.dart'; 8 | 9 | class AnimPanel extends StatefulWidget { 10 | @override 11 | _AnimPanelState createState() => _AnimPanelState(); 12 | } 13 | 14 | class _AnimPanelState extends State 15 | with SingleTickerProviderStateMixin { 16 | 17 | PointData points = PointData(); 18 | AnimationController _ctrl; 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | _ctrl = AnimationController( 25 | vsync: this, 26 | duration: animDuration, 27 | )..addListener(_collectPoint)..addStatusListener(_listenStatus); 28 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 29 | } 30 | 31 | @override 32 | void dispose() { 33 | _ctrl.dispose(); 34 | points.dispose(); 35 | super.dispose(); 36 | } 37 | 38 | void _collectPoint() { 39 | points.push(_ctrl.value); 40 | } 41 | 42 | void _listenStatus(AnimationStatus status){ 43 | // print(status); 44 | // if(status == AnimationStatus.reverse){ 45 | // points.clear(); 46 | // } 47 | } 48 | 49 | void _startAnim() async{ 50 | points.clear(); 51 | Timer(Duration(milliseconds: 1500),_stop); 52 | print('start!---${DateTime.now().toIso8601String()}----------'); 53 | _ctrl.repeat(reverse: true).orCancel.then((v) { 54 | print('cancel!---${DateTime.now().toIso8601String()}----------'); 55 | },onError: (e){ 56 | print('cancel!---$e----------'); 57 | }); 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return GestureDetector( 63 | onTap: _startAnim, 64 | onDoubleTap: _restartAnim, 65 | child: CustomPaint( 66 | painter: AnimPainter(points), 67 | size: const Size( 68 | 400, 69 | 200, 70 | ), 71 | ), 72 | ); 73 | } 74 | 75 | void _stop() { 76 | _ctrl.stop(canceled: true); 77 | } 78 | 79 | void _restartAnim() { 80 | _ctrl.reverse(); 81 | } 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /lib/02/02_function/04_stop/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/04_stop/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/05_fling/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/physics.dart'; 6 | 7 | import 'anim_painter.dart'; 8 | import 'point_data.dart'; 9 | 10 | class AnimPanel extends StatefulWidget { 11 | @override 12 | _AnimPanelState createState() => _AnimPanelState(); 13 | } 14 | 15 | class _AnimPanelState extends State 16 | with SingleTickerProviderStateMixin { 17 | 18 | PointData points = PointData(); 19 | AnimationController _ctrl; 20 | final Duration animDuration = const Duration(milliseconds: 1000); 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | _ctrl = AnimationController( 26 | vsync: this, 27 | duration: animDuration, 28 | )..addListener(_collectPoint); 29 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 30 | } 31 | 32 | @override 33 | void dispose() { 34 | _ctrl.dispose(); 35 | points.dispose(); 36 | super.dispose(); 37 | } 38 | 39 | void _collectPoint() { 40 | points.push(_ctrl.value); 41 | } 42 | 43 | 44 | void _startAnim() async{ 45 | points.clear(); 46 | _ctrl.reset(); 47 | print('fling start!---${DateTime.now().toIso8601String()}----------'); 48 | await _ctrl.fling( 49 | velocity: 10, 50 | springDescription: SpringDescription.withDampingRatio( 51 | mass: 1.0, 52 | stiffness: 500.0, 53 | ratio: 3.0, 54 | ) 55 | ); 56 | print('fling end!---${DateTime.now().toIso8601String()}----------'); 57 | 58 | } 59 | 60 | @override 61 | Widget build(BuildContext context) { 62 | return GestureDetector( 63 | onTap: _startAnim, 64 | child: CustomPaint( 65 | painter: AnimPainter(points), 66 | size: const Size( 67 | 200, 68 | 200, 69 | ), 70 | ), 71 | ); 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /lib/02/02_function/05_fling/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/05_fling/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/06_fling_spring/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/physics.dart'; 6 | import 'package:ianim/02/02_function/06_fling_spring/spring_painter.dart'; 7 | 8 | import 'anim_painter.dart'; 9 | import 'point_data.dart'; 10 | 11 | class AnimPanel extends StatefulWidget { 12 | @override 13 | _AnimPanelState createState() => _AnimPanelState(); 14 | } 15 | 16 | class _AnimPanelState extends State 17 | with SingleTickerProviderStateMixin { 18 | 19 | PointData points = PointData(); 20 | AnimationController _ctrl; 21 | final Duration animDuration = const Duration(milliseconds: 1000); 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | upperBound: 100, 30 | lowerBound: 50 31 | )..addListener(_collectPoint); 32 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 33 | } 34 | 35 | @override 36 | void dispose() { 37 | _ctrl.dispose(); 38 | points.dispose(); 39 | super.dispose(); 40 | } 41 | 42 | void _collectPoint() { 43 | points.push(_ctrl.value); 44 | } 45 | 46 | 47 | void _startAnim() async{ 48 | points.clear(); 49 | _ctrl.reset(); 50 | print('fling start!---${DateTime.now().toIso8601String()}----------'); 51 | await _ctrl.fling( 52 | velocity: 10, 53 | springDescription: SpringDescription.withDampingRatio( 54 | mass: 1.0, 55 | stiffness: 1000.0, 56 | ratio: 3.0, 57 | ) 58 | ); 59 | print('fling end!---${DateTime.now().toIso8601String()}----------'); 60 | 61 | } 62 | 63 | @override 64 | Widget build(BuildContext context) { 65 | return GestureDetector( 66 | onTap: _startAnim, 67 | child: Container( 68 | width: 200, 69 | height: 200, 70 | color: Colors.grey.withAlpha(11), 71 | child: CustomPaint( 72 | painter: SpringPainter(height: _ctrl)), 73 | ), 74 | ); 75 | } 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /lib/02/02_function/06_fling_spring/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/02_function/06_fling_spring/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/02/02_function/06_fling_spring/spring_painter.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | const double _kSpringWidth = 30; 5 | 6 | class SpringPainter extends CustomPainter { 7 | final int count; 8 | final ValueListenable height; 9 | 10 | SpringPainter({this.count = 20, @required this.height}):super(repaint: height); 11 | 12 | Paint _paint = Paint() 13 | ..style = PaintingStyle.stroke 14 | ..strokeWidth = 1; 15 | 16 | @override 17 | void paint(Canvas canvas, Size size) { 18 | canvas.translate(size.width / 2+_kSpringWidth / 2, size.height); 19 | Path springPath = Path(); 20 | springPath.relativeLineTo(-_kSpringWidth, 0); 21 | double space = height.value/(count+1); 22 | 23 | for (int i = 1; i < count; i++) { 24 | if (i % 2 == 1) { 25 | springPath.relativeLineTo(_kSpringWidth, -space); 26 | } else { 27 | springPath.relativeLineTo(-_kSpringWidth, -space); 28 | } 29 | } 30 | 31 | if(count.isOdd){ 32 | springPath.relativeLineTo(_kSpringWidth, 0); 33 | }else{ 34 | springPath.relativeLineTo(-_kSpringWidth, 0); 35 | } 36 | 37 | canvas.drawPath(springPath, _paint); 38 | } 39 | 40 | @override 41 | bool shouldRepaint(covariant SpringPainter oldDelegate) => 42 | oldDelegate.count != count || oldDelegate.height != height; 43 | } 44 | -------------------------------------------------------------------------------- /lib/02/03_status/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | // Animation curve; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint)..addStatusListener(_listenStatus); 30 | // curve = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 31 | } 32 | 33 | void _listenStatus(AnimationStatus status) { 34 | print(status); 35 | } 36 | 37 | @override 38 | void dispose() { 39 | _ctrl.dispose(); 40 | points.dispose(); 41 | super.dispose(); 42 | } 43 | 44 | void _collectPoint() { 45 | points.push(_ctrl.value); 46 | } 47 | 48 | void _startAnim() async{ 49 | points.clear(); 50 | print('start!---${DateTime.now().toIso8601String()}----------'); 51 | // await _ctrl.forward(); 52 | await _ctrl.reverse(from: 0.5); 53 | print('done!---${DateTime.now().toIso8601String()}----------'); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return GestureDetector( 59 | onTap: _startAnim, 60 | child: CustomPaint( 61 | painter: AnimPainter(points), 62 | size: const Size( 63 | 200, 64 | 200, 65 | ), 66 | ), 67 | ); 68 | } 69 | 70 | 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /lib/02/03_status/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/02/03_status/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/03_curve/01/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | Animation curveAnim; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | curveAnim = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 31 | } 32 | 33 | @override 34 | void dispose() { 35 | _ctrl.dispose(); 36 | points.dispose(); 37 | super.dispose(); 38 | } 39 | 40 | void _collectPoint() { 41 | points.push(curveAnim.value); 42 | } 43 | 44 | void _startAnim() async{ 45 | points.clear(); 46 | print('start!---${DateTime.now().toIso8601String()}----------'); 47 | // await _ctrl.forward(from: 0); 48 | await _ctrl.forward(from: 0); 49 | print('done!---${DateTime.now().toIso8601String()}----------'); 50 | } 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return GestureDetector( 55 | onTap: _startAnim, 56 | child: CustomPaint( 57 | painter: AnimPainter(points), 58 | size: const Size( 59 | 200, 60 | 200, 61 | ), 62 | ), 63 | ); 64 | } 65 | } 66 | 67 | 68 | -------------------------------------------------------------------------------- /lib/03_curve/01/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/03_curve/01/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/03_curve/02/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | Animation curveAnim; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | // curveAnim = CurvedAnimation(parent: _ctrl, curve: Curves.bounceOut); 31 | // curveAnim = CurvedAnimation(parent: _ctrl, curve: Curves.ease); 32 | // curveAnim = CurvedAnimation(parent: _ctrl, curve: Curves.decelerate); 33 | // curveAnim = CurvedAnimation(parent: _ctrl, curve: Curves.elasticOut); 34 | curveAnim = CurvedAnimation(parent: _ctrl, curve: const SawTooth(3)); 35 | } 36 | 37 | @override 38 | void dispose() { 39 | _ctrl.dispose(); 40 | points.dispose(); 41 | super.dispose(); 42 | } 43 | 44 | void _collectPoint() { 45 | points.push(curveAnim.value); 46 | } 47 | 48 | void _startAnim() async{ 49 | points.clear(); 50 | print('start!---${DateTime.now().toIso8601String()}----------'); 51 | // await _ctrl.forward(from: 0); 52 | await _ctrl.forward(from: 0); 53 | print('done!---${DateTime.now().toIso8601String()}----------'); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return GestureDetector( 59 | onTap: _startAnim, 60 | child: CustomPaint( 61 | painter: AnimPainter(points), 62 | size: const Size( 63 | 200, 64 | 200, 65 | ), 66 | ), 67 | ); 68 | } 69 | } 70 | 71 | 72 | -------------------------------------------------------------------------------- /lib/03_curve/02/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/03_curve/02/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/03_curve/03/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | // Animation curveAnim; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | } 31 | 32 | @override 33 | void dispose() { 34 | _ctrl.dispose(); 35 | points.dispose(); 36 | super.dispose(); 37 | } 38 | 39 | void _collectPoint() { 40 | points.push(Curves.decelerate.transform(_ctrl.value)); 41 | } 42 | 43 | void _startAnim() async{ 44 | points.clear(); 45 | print('start!---${DateTime.now().toIso8601String()}----------'); 46 | // await _ctrl.forward(from: 0); 47 | await _ctrl.forward(from: 0); 48 | print('done!---${DateTime.now().toIso8601String()}----------'); 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return GestureDetector( 54 | onTap: _startAnim, 55 | child: CustomPaint( 56 | painter: AnimPainter(points), 57 | size: const Size( 58 | 200, 59 | 200, 60 | ), 61 | ), 62 | ); 63 | } 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /lib/03_curve/03/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/03_curve/03/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/03_curve/04/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | import 'toly_curve.dart'; 8 | 9 | class AnimPanel extends StatefulWidget { 10 | @override 11 | _AnimPanelState createState() => _AnimPanelState(); 12 | } 13 | 14 | class _AnimPanelState extends State 15 | with SingleTickerProviderStateMixin { 16 | PointData points = PointData(); 17 | 18 | AnimationController _ctrl; 19 | 20 | final Duration animDuration = const Duration(milliseconds: 1000); 21 | 22 | Animation curveAnim; 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | _ctrl = AnimationController( 28 | vsync: this, 29 | duration: animDuration, 30 | )..addListener(_collectPoint); 31 | // curveAnim = CurvedAnimation(parent: _ctrl, curve: const X2Curve()); 32 | curveAnim = CurvedAnimation(parent: _ctrl, curve: const DampingCurve()); 33 | 34 | } 35 | 36 | @override 37 | void dispose() { 38 | _ctrl.dispose(); 39 | points.dispose(); 40 | super.dispose(); 41 | } 42 | 43 | void _collectPoint() { 44 | points.push(curveAnim.value); 45 | } 46 | 47 | void _startAnim() async{ 48 | points.clear(); 49 | print('start!---${DateTime.now().toIso8601String()}----------'); 50 | // await _ctrl.forward(from: 0); 51 | await _ctrl.forward(from: 0); 52 | print('done!---${DateTime.now().toIso8601String()}----------'); 53 | } 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return GestureDetector( 58 | onTap: _startAnim, 59 | child: CustomPaint( 60 | painter: AnimPainter(points), 61 | size: const Size( 62 | 200, 63 | 200, 64 | ), 65 | ), 66 | ); 67 | } 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /lib/03_curve/04/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/03_curve/04/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/03_curve/04/toly_curve.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class X2Curve extends Curve{ 6 | 7 | const X2Curve(); 8 | 9 | 10 | @override 11 | double transformInternal(double t) { 12 | return t*t; 13 | } 14 | 15 | } 16 | 17 | class DampingCurve extends Curve { 18 | const DampingCurve(); 19 | 20 | @override 21 | double transformInternal(double t) { 22 | t = t - 1.0; 23 | return t * t * t * t * t + 1.0; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/04_tween/01_color/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds: 1000); 13 | 14 | @override 15 | void initState() { 16 | super.initState(); 17 | _ctrl = AnimationController( 18 | vsync: this, 19 | duration: animDuration, 20 | ); 21 | } 22 | 23 | @override 24 | void dispose() { 25 | _ctrl.dispose(); 26 | super.dispose(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return GestureDetector( 32 | onTap: _startAnim, 33 | child: AnimatedBuilder( 34 | animation: _ctrl, 35 | builder: _buildByAnim, 36 | )); 37 | } 38 | 39 | Color get color => Color.lerp(Colors.blue, Colors.red, _ctrl.value); 40 | 41 | Widget _buildByAnim(_, __) => Container( 42 | width: 80, 43 | height: 80, 44 | decoration: BoxDecoration(color: color, shape: BoxShape.circle), 45 | ); 46 | 47 | void _startAnim() { 48 | _ctrl.forward(from: 0); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/04_tween/01_color/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/02_color_tween/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds: 1000); 13 | 14 | final ColorTween tween = ColorTween(begin: Colors.blue,end: Colors.red); 15 | 16 | @override 17 | void initState() { 18 | super.initState(); 19 | _ctrl = AnimationController( 20 | vsync: this, 21 | duration: animDuration, 22 | ); 23 | } 24 | 25 | @override 26 | void dispose() { 27 | _ctrl.dispose(); 28 | super.dispose(); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return GestureDetector( 34 | onTap: _startAnim, 35 | child: AnimatedBuilder( 36 | animation: _ctrl, 37 | builder: _buildByAnim, 38 | )); 39 | } 40 | 41 | Color get color => tween.transform(_ctrl.value); 42 | 43 | Widget _buildByAnim(_, __) => Container( 44 | width: 80, 45 | height: 80, 46 | decoration: BoxDecoration(color: color, shape: BoxShape.circle), 47 | ); 48 | 49 | void _startAnim() { 50 | _ctrl.forward(from: 0); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/04_tween/02_color_tween/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/03_tween_evaluate/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds: 1000); 13 | 14 | final ColorTween tween = ColorTween(begin: Colors.blue,end: Colors.red); 15 | 16 | @override 17 | void initState() { 18 | super.initState(); 19 | _ctrl = AnimationController( 20 | vsync: this, 21 | duration: animDuration, 22 | ); 23 | } 24 | 25 | @override 26 | void dispose() { 27 | _ctrl.dispose(); 28 | super.dispose(); 29 | } 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return GestureDetector( 34 | onTap: _startAnim, 35 | child: AnimatedBuilder( 36 | animation: _ctrl, 37 | builder: _buildByAnim, 38 | )); 39 | } 40 | 41 | Color get color => tween.evaluate(_ctrl); 42 | 43 | Widget _buildByAnim(_, __) => Container( 44 | width: 80, 45 | height: 80, 46 | decoration: BoxDecoration(color: color, shape: BoxShape.circle), 47 | ); 48 | 49 | void _startAnim() { 50 | _ctrl.forward(from: 0); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/04_tween/03_tween_evaluate/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/04_animate/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | final Duration animDuration = const Duration(milliseconds: 1000); 13 | 14 | final ColorTween tween = ColorTween(begin: Colors.blue,end: Colors.red); 15 | Animation colorAnima; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | _ctrl = AnimationController( 21 | vsync: this, 22 | duration: animDuration, 23 | ); 24 | colorAnima = tween.animate(_ctrl); 25 | } 26 | 27 | @override 28 | void dispose() { 29 | _ctrl.dispose(); 30 | super.dispose(); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return GestureDetector( 36 | onTap: _startAnim, 37 | child: AnimatedBuilder( 38 | animation: _ctrl, 39 | builder: _buildByAnim, 40 | )); 41 | } 42 | 43 | Color get color => colorAnima.value; 44 | 45 | Widget _buildByAnim(_, __) => Container( 46 | width: 80, 47 | height: 80, 48 | decoration: BoxDecoration(color: color, shape: BoxShape.circle), 49 | ); 50 | 51 | void _startAnim() { 52 | _ctrl.forward(from: 0); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/04_tween/04_animate/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/05_curve_tween/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | Animation curveAnim; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | curveAnim = CurveTween(curve: Curves.bounceOut).animate(_ctrl); 31 | 32 | 33 | 34 | } 35 | 36 | @override 37 | void dispose() { 38 | _ctrl.dispose(); 39 | points.dispose(); 40 | super.dispose(); 41 | } 42 | 43 | void _collectPoint() { 44 | points.push(curveAnim.value); 45 | } 46 | 47 | void _startAnim() async{ 48 | points.clear(); 49 | print('start!---${DateTime.now().toIso8601String()}----------'); 50 | // await _ctrl.forward(from: 0); 51 | await _ctrl.forward(from: 0); 52 | print('done!---${DateTime.now().toIso8601String()}----------'); 53 | } 54 | 55 | @override 56 | Widget build(BuildContext context) { 57 | return GestureDetector( 58 | onTap: _startAnim, 59 | child: CustomPaint( 60 | painter: AnimPainter(points), 61 | size: const Size( 62 | 200, 63 | 200, 64 | ), 65 | ), 66 | ); 67 | } 68 | } 69 | 70 | 71 | -------------------------------------------------------------------------------- /lib/04_tween/05_curve_tween/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/05_curve_tween/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/04_tween/06_tween_sequence/anim_panel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'anim_painter.dart'; 6 | import 'point_data.dart'; 7 | 8 | class AnimPanel extends StatefulWidget { 9 | @override 10 | _AnimPanelState createState() => _AnimPanelState(); 11 | } 12 | 13 | class _AnimPanelState extends State 14 | with SingleTickerProviderStateMixin { 15 | PointData points = PointData(); 16 | 17 | AnimationController _ctrl; 18 | 19 | final Duration animDuration = const Duration(milliseconds: 1000); 20 | 21 | Animation sequenceAnim; 22 | 23 | @override 24 | void initState() { 25 | super.initState(); 26 | _ctrl = AnimationController( 27 | vsync: this, 28 | duration: animDuration, 29 | )..addListener(_collectPoint); 30 | 31 | sequenceAnim = TweenSequence( 32 | >[ 33 | TweenSequenceItem( 34 | tween: Tween(begin: 0,end: 0.5).chain(CurveTween(curve: Curves.ease)), 35 | weight: 4.0, 36 | ), 37 | TweenSequenceItem( 38 | tween: ConstantTween(0.5), 39 | weight: 2.0, 40 | ), 41 | TweenSequenceItem( 42 | tween: Tween(begin: 0.5,end: 1.0).chain(CurveTween(curve: Curves.decelerate)), 43 | weight: 4.0, 44 | ), 45 | ], 46 | ).animate(_ctrl); 47 | } 48 | 49 | @override 50 | void dispose() { 51 | _ctrl.dispose(); 52 | points.dispose(); 53 | super.dispose(); 54 | } 55 | 56 | void _collectPoint() { 57 | points.push(sequenceAnim.value); 58 | } 59 | 60 | void _startAnim() async{ 61 | points.clear(); 62 | print('start!---${DateTime.now().toIso8601String()}----------'); 63 | // await _ctrl.forward(from: 0); 64 | await _ctrl.forward(from: 0); 65 | print('done!---${DateTime.now().toIso8601String()}----------'); 66 | } 67 | 68 | @override 69 | Widget build(BuildContext context) { 70 | return GestureDetector( 71 | onTap: _startAnim, 72 | child: CustomPaint( 73 | painter: AnimPainter(points), 74 | size: const Size( 75 | 200, 76 | 200, 77 | ), 78 | ), 79 | ); 80 | } 81 | } 82 | 83 | 84 | -------------------------------------------------------------------------------- /lib/04_tween/06_tween_sequence/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'anim_panel.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimPanel(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/06_tween_sequence/point_data.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class PointData extends ChangeNotifier { 4 | final List values = []; 5 | 6 | void push(double value) { 7 | values.add(value); 8 | notifyListeners(); 9 | } 10 | 11 | 12 | void clear() { 13 | values.clear(); 14 | notifyListeners(); 15 | } 16 | } -------------------------------------------------------------------------------- /lib/04_tween/07_text_style_tween/circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class Circle { 4 | final Color color; 5 | final double radius; 6 | final Offset center; 7 | 8 | Circle({this.color, this.radius, this.center}); 9 | } 10 | 11 | class CircleTween extends Tween { 12 | CircleTween({Circle begin, Circle end}) : super(begin: begin, end: end); 13 | 14 | @override 15 | Circle lerp(double t) { 16 | return Circle( 17 | color: Color.lerp(begin.color, end.color, t), 18 | radius: (begin.radius + (end.radius - begin.radius) * t), 19 | center: Offset.lerp(begin.center, end.center, t)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/04_tween/07_text_style_tween/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'circle.dart'; 4 | 5 | class CircleAnim extends StatefulWidget { 6 | @override 7 | _CircleAnimState createState() => _CircleAnimState(); 8 | } 9 | 10 | class _CircleAnimState extends State 11 | with SingleTickerProviderStateMixin { 12 | AnimationController _ctrl; 13 | 14 | final Duration animDuration = const Duration(milliseconds: 500); 15 | 16 | final TextStyleTween tween = TextStyleTween( 17 | begin: TextStyle(color: Colors.blue, fontSize: 14, letterSpacing: 4,), 18 | end: TextStyle(color: Colors.purple, fontSize: 40, letterSpacing: 10,)); 19 | 20 | Animation textAnimation; 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | _ctrl = AnimationController( 26 | vsync: this, 27 | duration: animDuration, 28 | ); 29 | textAnimation = tween.animate(_ctrl); 30 | } 31 | 32 | @override 33 | void dispose() { 34 | _ctrl.dispose(); 35 | super.dispose(); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return GestureDetector( 41 | behavior: HitTestBehavior.opaque, 42 | onTap: _startAnim, 43 | child: Center( 44 | child: AnimatedBuilder( 45 | animation: _ctrl, 46 | builder: _buildByAnim, 47 | ), 48 | )); 49 | } 50 | 51 | Widget _buildByAnim(_, __) => Text( 52 | "张风捷特烈",style: textAnimation.value, 53 | ); 54 | 55 | void _startAnim() { 56 | _ctrl.forward(from: 0); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/04_tween/07_text_style_tween/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/04_tween/08_circle_color_tween/circle.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | class Circle { 4 | final Color color; 5 | final double radius; 6 | final Offset center; 7 | 8 | Circle({this.color, this.radius, this.center}); 9 | } 10 | 11 | class CircleTween extends Tween { 12 | CircleTween({Circle begin, Circle end}) : super(begin: begin, end: end); 13 | 14 | @override 15 | Circle lerp(double t) { 16 | return Circle( 17 | color: Color.lerp(begin.color, end.color, t), 18 | radius: (begin.radius + (end.radius - begin.radius) * t), 19 | center: Offset.lerp(begin.center, end.center, t)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/04_tween/08_circle_color_tween/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'circle.dart'; 4 | 5 | class CircleAnim extends StatefulWidget { 6 | @override 7 | _CircleAnimState createState() => _CircleAnimState(); 8 | } 9 | 10 | class _CircleAnimState extends State 11 | with SingleTickerProviderStateMixin { 12 | AnimationController _ctrl; 13 | 14 | final Duration animDuration = const Duration(milliseconds: 1000); 15 | 16 | final CircleTween tween = CircleTween( 17 | begin: Circle(center: Offset.zero, radius: 25, color: Colors.blue), 18 | end: Circle(center: Offset(100, 0), radius: 50, color: Colors.red)); 19 | 20 | Animation circleAnimation; 21 | 22 | @override 23 | void initState() { 24 | super.initState(); 25 | _ctrl = AnimationController( 26 | vsync: this, 27 | duration: animDuration, 28 | ); 29 | circleAnimation = tween.animate(_ctrl); 30 | } 31 | 32 | @override 33 | void dispose() { 34 | _ctrl.dispose(); 35 | super.dispose(); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return GestureDetector( 41 | behavior: HitTestBehavior.opaque, 42 | onTap: _startAnim, 43 | child: AnimatedBuilder( 44 | animation: _ctrl, 45 | builder: _buildByAnim, 46 | )); 47 | } 48 | 49 | Widget _buildByAnim(_, __) =>CircleWidget( 50 | circle: circleAnimation.value, 51 | ); 52 | 53 | void _startAnim() { 54 | _ctrl.forward(from: 0); 55 | } 56 | } 57 | 58 | class CircleWidget extends StatelessWidget { 59 | final Circle circle; 60 | const CircleWidget({Key key,@required this.circle}) : super(key: key); 61 | 62 | @override 63 | Widget build(BuildContext context) { 64 | return Container( 65 | transform: Matrix4.translationValues(circle.center.dx, 66 | circle.center.dy, 0), 67 | width: circle.radius * 2, 68 | height: circle.radius * 2, 69 | decoration: BoxDecoration( 70 | color: circle.color, shape: BoxShape.circle), 71 | ); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/04_tween/08_circle_color_tween/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/05_simple/01_shine_static/circle_shine_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleShineImage extends StatefulWidget { 4 | final double maxBlurRadius; 5 | final Color color; 6 | final Duration duration; 7 | final Curve curve; 8 | final ImageProvider image; 9 | final double radius; 10 | 11 | const CircleShineImage( 12 | {Key key, 13 | this.maxBlurRadius = 10, 14 | this.color = Colors.purple, 15 | this.duration = const Duration(milliseconds: 2000), 16 | this.curve = Curves.ease, 17 | this.radius = 30, 18 | @required this.image}) 19 | : super(key: key); 20 | 21 | @override 22 | _CircleShineImageState createState() => _CircleShineImageState(); 23 | } 24 | 25 | class _CircleShineImageState extends State { 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Container( 30 | height: widget.radius * 2, 31 | width: widget.radius * 2, 32 | decoration: BoxDecoration( 33 | image: DecorationImage(image: widget.image, fit: BoxFit.cover), 34 | shape: BoxShape.circle, 35 | boxShadow: [ 36 | BoxShadow( 37 | color: widget.color, 38 | blurRadius: widget.maxBlurRadius, 39 | spreadRadius: 0) 40 | ]), 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/05_simple/01_shine_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_shine_image.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleShineImage( 29 | image: AssetImage('assets/images/icon_head.png'), 30 | color: Colors.blue, 31 | maxBlurRadius: 4, 32 | curve: Curves.decelerate, 33 | ), 34 | CircleShineImage( 35 | image: AssetImage('assets/images/icon_head.png'), 36 | color: Colors.red, 37 | maxBlurRadius: 6, 38 | duration: Duration(seconds: 1), 39 | curve: Curves.easeIn, 40 | ), 41 | CircleShineImage( 42 | image: AssetImage('assets/images/icon_head.png'), 43 | color: Colors.purple, 44 | maxBlurRadius: 8, 45 | curve: Curves.ease, 46 | ), 47 | 48 | ] , 49 | ), 50 | )) 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/05_simple/02_shine_anim/circle_shine_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleShineImage extends StatefulWidget { 4 | final double maxBlurRadius; 5 | final Color color; 6 | final Duration duration; 7 | final Curve curve; 8 | final ImageProvider image; 9 | final double radius; 10 | 11 | const CircleShineImage( 12 | {Key key, 13 | this.maxBlurRadius = 10, 14 | this.color = Colors.purple, 15 | this.duration = const Duration(milliseconds: 2000), 16 | this.curve = Curves.ease, 17 | this.radius = 30, 18 | @required this.image}) 19 | : super(key: key); 20 | 21 | @override 22 | _CircleShineImageState createState() => _CircleShineImageState(); 23 | } 24 | 25 | class _CircleShineImageState extends State 26 | with SingleTickerProviderStateMixin { 27 | AnimationController _ctrl; 28 | Animation blurRadiusAnim; 29 | 30 | @override 31 | void initState() { 32 | super.initState(); 33 | _ctrl = AnimationController( 34 | vsync: this, 35 | duration: widget.duration, 36 | )..addListener(_handleAnimationChanged); 37 | 38 | blurRadiusAnim = Tween(begin: 0, end: widget.maxBlurRadius) 39 | .chain(CurveTween(curve: widget.curve)) 40 | .animate(_ctrl); 41 | 42 | _ctrl.repeat(reverse: true); 43 | } 44 | 45 | @override 46 | void dispose() { 47 | _ctrl.dispose(); 48 | super.dispose(); 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return Container( 54 | height: widget.radius * 2, 55 | width: widget.radius * 2, 56 | decoration: BoxDecoration( 57 | image: DecorationImage(image: widget.image, fit: BoxFit.cover), 58 | shape: BoxShape.circle, 59 | boxShadow: [ 60 | BoxShadow( 61 | color: widget.color, 62 | blurRadius: blurRadiusAnim.value, 63 | spreadRadius: 0) 64 | ]), 65 | ); 66 | } 67 | 68 | void _handleAnimationChanged() { 69 | setState(() {}); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/05_simple/02_shine_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_shine_image.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleShineImage( 29 | image: AssetImage('assets/images/wy_300x200.jpg'), 30 | color: Colors.red, 31 | maxBlurRadius: 6, 32 | duration: Duration(seconds: 1), 33 | curve: Curves.easeIn, 34 | ), 35 | CircleShineImage( 36 | image: AssetImage('assets/images/icon_head.png'), 37 | color: Colors.purple, 38 | maxBlurRadius: 8, 39 | curve: Curves.ease, 40 | ), 41 | CircleShineImage( 42 | image: AssetImage('assets/images/icon_8.jpg'), 43 | color: Colors.blue, 44 | maxBlurRadius: 4, 45 | curve: Curves.decelerate, 46 | ) 47 | ] , 48 | ), 49 | )) 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/05_simple/04_compare/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'toggle_rotate.dart'; 5 | 6 | void main() { 7 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 8 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 9 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 10 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 11 | runApp(MyApp()); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | @override 16 | Widget build(BuildContext context) { 17 | return MaterialApp( 18 | debugShowCheckedModeBanner: false, 19 | title: 'Flutter Demo', 20 | theme: ThemeData( 21 | primarySwatch: Colors.blue, 22 | ), 23 | home: HomePage()); 24 | } 25 | } 26 | 27 | class HomePage extends StatefulWidget { 28 | const HomePage({Key key}) : super(key: key); 29 | 30 | @override 31 | _HomePageState createState() => _HomePageState(); 32 | } 33 | 34 | class _HomePageState extends State { 35 | ValueNotifier angle = ValueNotifier(90); 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Scaffold( 40 | // backgroundColor: Colors.black, 41 | body: Center( 42 | child: Container( 43 | width: 300, 44 | child: ValueListenableBuilder( 45 | valueListenable: angle, 46 | builder: (_, value, __) => Wrap( 47 | alignment: WrapAlignment.center, 48 | children: [ 49 | Slider( 50 | value: value, 51 | min: 0, 52 | max: 360, 53 | onChanged: (v) { 54 | angle.value = v; 55 | }), 56 | ToggleRotate( 57 | beginAngle: 0, 58 | endAngle: value, 59 | curve: Curves.ease, 60 | child: Image( 61 | width: 60, 62 | height: 60, 63 | image: AssetImage("assets/images/icon_head.jpg")), 64 | onEnd: (v) { 65 | print("---expanded---:$v-------"); 66 | }, 67 | onTap: () { 68 | print("---tap----------"); 69 | }, 70 | ) 71 | ], 72 | )), 73 | ), 74 | )); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/05_simple/05_burst_static/burst_menu.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | /// create by 张风捷特烈 on 2020/11/17 6 | /// contact me by email 1981462002@qq.com 7 | /// 说明: 8 | 9 | class BurstMenu extends StatefulWidget { 10 | final List menus; 11 | final Widget center; 12 | 13 | BurstMenu({Key key, @required this.menus, @required this.center}) 14 | : super(key: key); 15 | 16 | @override 17 | BurstMenuState createState() => BurstMenuState(); 18 | } 19 | 20 | class BurstMenuState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return Flow( 24 | delegate: _CircleFlowDelegate(), 25 | children: [...widget.menus, widget.center], 26 | ); 27 | } 28 | } 29 | 30 | class _CircleFlowDelegate extends FlowDelegate { 31 | //绘制孩子的方法 32 | @override 33 | void paintChildren(FlowPaintingContext context) { 34 | 35 | double radius = context.size.shortestSide / 2; 36 | 37 | final int count = context.childCount - 1; 38 | final double perRad = 2 * pi / count; 39 | 40 | for (int i = 0; i < count; i++) { 41 | final double cSizeX = context.getChildSize(i).width / 2; 42 | final double cSizeY = context.getChildSize(i).height / 2; 43 | 44 | final double offsetX = (radius - cSizeX) * cos(i * perRad) + radius; 45 | final double offsetY = (radius - cSizeY) * sin(i * perRad) + radius; 46 | 47 | context.paintChild( 48 | i, 49 | transform: Matrix4.translationValues( 50 | offsetX - cSizeX, 51 | offsetY - cSizeY, 52 | 0.0, 53 | ), 54 | ); 55 | } 56 | 57 | context.paintChild( 58 | context.childCount - 1, 59 | transform: Matrix4.translationValues( 60 | radius - context.getChildSize(context.childCount - 1).width / 2, 61 | radius - context.getChildSize(context.childCount - 1).height / 2, 62 | 0.0, 63 | ), 64 | ); 65 | } 66 | 67 | @override 68 | bool shouldRepaint(FlowDelegate oldDelegate) => false; 69 | } 70 | -------------------------------------------------------------------------------- /lib/05_simple/06_burst_static_angle/burst_menu.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | /// create by 张风捷特烈 on 2020/11/17 6 | /// contact me by email 1981462002@qq.com 7 | /// 说明: 8 | 9 | class BurstMenu extends StatefulWidget { 10 | final List menus; 11 | final Widget center; 12 | 13 | BurstMenu({Key key, @required this.menus, @required this.center}) 14 | : super(key: key); 15 | 16 | @override 17 | BurstMenuState createState() => BurstMenuState(); 18 | } 19 | 20 | class BurstMenuState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return Flow( 24 | delegate: _CircleFlowDelegate(), 25 | children: [...widget.menus, widget.center], 26 | ); 27 | } 28 | } 29 | 30 | class _CircleFlowDelegate extends FlowDelegate { 31 | // 菜单圆弧的扫描角度 32 | final double swapAngle; 33 | 34 | // 菜单圆弧的起始角度 35 | final double startAngle; 36 | 37 | _CircleFlowDelegate({ 38 | this.swapAngle = 120, 39 | this.startAngle = -60, 40 | }); 41 | 42 | //绘制孩子的方法 43 | @override 44 | void paintChildren(FlowPaintingContext context) { 45 | double radius = context.size.shortestSide / 2; 46 | final int count = context.childCount - 1; 47 | 48 | final double perRad = swapAngle / 180 * pi / (count - 1); 49 | double rotate = startAngle / 180 * pi; 50 | 51 | for (int i = 0; i < count; i++) { 52 | final double cSizeX = context.getChildSize(i).width / 2; 53 | final double cSizeY = context.getChildSize(i).height / 2; 54 | 55 | final double offsetX = 56 | (radius - cSizeX) * cos(i * perRad + rotate) + radius; 57 | final double offsetY = 58 | (radius - cSizeY) * sin(i * perRad + rotate) + radius; 59 | 60 | context.paintChild( 61 | i, 62 | transform: Matrix4.translationValues( 63 | offsetX - cSizeX, 64 | offsetY - cSizeY, 65 | 0.0, 66 | ), 67 | ); 68 | } 69 | 70 | context.paintChild( 71 | context.childCount - 1, 72 | transform: Matrix4.translationValues( 73 | radius - context.getChildSize(context.childCount - 1).width / 2, 74 | radius - context.getChildSize(context.childCount - 1).height / 2, 75 | 0.0, 76 | ), 77 | ); 78 | } 79 | 80 | @override 81 | bool shouldRepaint(_CircleFlowDelegate oldDelegate) => 82 | swapAngle != oldDelegate.swapAngle || 83 | startAngle != oldDelegate.startAngle; 84 | } 85 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/01_circle_static/circle_halo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui' as ui; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | class CircleHalo extends StatefulWidget { 7 | const CircleHalo({Key key}) : super(key: key); 8 | 9 | @override 10 | _CircleHaloState createState() => _CircleHaloState(); 11 | } 12 | 13 | class _CircleHaloState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return CustomPaint( 17 | size: Size(200, 200), 18 | painter: CircleHaloPainter(), 19 | ); 20 | } 21 | } 22 | 23 | class CircleHaloPainter extends CustomPainter { 24 | @override 25 | void paint(Canvas canvas, Size size) { 26 | canvas.translate(size.width / 2, size.height / 2); 27 | final Paint paint = Paint() 28 | ..style = PaintingStyle.stroke 29 | ..strokeWidth = 1; 30 | 31 | List colors = [ 32 | Color(0xFFF60C0C), 33 | Color(0xFFF3B913), 34 | Color(0xFFE7F716), 35 | Color(0xFF3DF30B), 36 | Color(0xFF0DF6EF), 37 | Color(0xFF0829FB), 38 | Color(0xFFB709F4), 39 | ]; 40 | colors.addAll(colors.reversed.toList()); 41 | final List pos = List.generate(colors.length, (index) => index / colors.length); 42 | 43 | paint.shader = 44 | ui.Gradient.sweep(Offset.zero, colors, pos, TileMode.clamp, 0, 2 * pi); 45 | 46 | paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 4); 47 | 48 | final Path circlePath = Path(); 49 | 50 | circlePath.addOval( 51 | Rect.fromCenter(center: Offset(0, 0), width: 100, height: 100)); 52 | 53 | canvas.drawPath(circlePath, paint); 54 | } 55 | 56 | @override 57 | bool shouldRepaint(covariant CustomPainter oldDelegate) => false; 58 | } 59 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/01_circle_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_halo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleHalo() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/02_light_static/circle_halo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui' as ui; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | class CircleHalo extends StatefulWidget { 7 | const CircleHalo({Key key}) : super(key: key); 8 | 9 | @override 10 | _CircleHaloState createState() => _CircleHaloState(); 11 | } 12 | 13 | class _CircleHaloState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return CustomPaint( 17 | size: Size(200, 200), 18 | painter: CircleHaloPainter(), 19 | ); 20 | } 21 | } 22 | 23 | class CircleHaloPainter extends CustomPainter { 24 | @override 25 | void paint(Canvas canvas, Size size) { 26 | canvas.translate(size.width / 2, size.height / 2); 27 | final Paint paint = Paint() 28 | ..style = PaintingStyle.stroke; 29 | 30 | paint.maskFilter = MaskFilter.blur(BlurStyle.solid, 4); 31 | 32 | final Path circlePath = Path()..addOval( 33 | Rect.fromCenter(center: Offset(0, 0), width: 100, height: 100)); 34 | 35 | Path circlePath2 = Path()..addOval( 36 | Rect.fromCenter(center: Offset(-1, 0), width: 100, height: 100)); 37 | 38 | Path result = Path.combine(PathOperation.difference, circlePath, circlePath2); 39 | paint.shader =null; 40 | paint..style = PaintingStyle.fill..color = Color(0xff00abf2); 41 | 42 | canvas.drawPath(result, paint); 43 | } 44 | 45 | @override 46 | bool shouldRepaint(covariant CustomPainter oldDelegate) => false; 47 | } 48 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/02_light_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_halo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleHalo() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/03_circle_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_halo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleHalo() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/04_light_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_halo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleHalo() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/01_halo_circle/05_circle_halo_last/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_halo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CircleHalo() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/02_rotate/01_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'rotate_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | RotateLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/02_rotate/01_static/rotate_loading.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class RotateLoading extends StatefulWidget { 4 | final double size; 5 | 6 | const RotateLoading({Key key, this.size = 100}) : super(key: key); 7 | 8 | @override 9 | _RotateLoadingState createState() => _RotateLoadingState(); 10 | } 11 | 12 | class _RotateLoadingState extends State { 13 | @override 14 | Widget build(BuildContext context) { 15 | return CustomPaint( 16 | size: Size(widget.size, widget.size), 17 | painter: RotateLoadingPainter(), 18 | ); 19 | } 20 | } 21 | 22 | class RotateLoadingPainter extends CustomPainter { 23 | final double itemWidth; 24 | 25 | RotateLoadingPainter({this.itemWidth = 33}); 26 | 27 | final List colors = const [ 28 | Color(0xffF44336), 29 | Color(0xff5C6BC0), 30 | Color(0xffFFB74D), 31 | Color(0xff8BC34A) 32 | ]; 33 | 34 | final Paint _paint = Paint(); 35 | final double span = 16; 36 | 37 | @override 38 | void paint(Canvas canvas, Size size) { 39 | canvas.translate(size.width / 2, size.height / 2); 40 | final double len = itemWidth / 2 + span / 2; 41 | 42 | // 绘制红色 43 | Offset centerA = Offset(-len, -len); 44 | drawItem(canvas, centerA, colors[0]); 45 | 46 | // 绘制蓝色 47 | Offset centerB = Offset(len, len); 48 | drawItem(canvas, centerB, colors[1]); 49 | 50 | // 绘制橙色 51 | Offset centerC = Offset(len, -len); 52 | drawItem(canvas, centerC, colors[2]); 53 | 54 | // 绘制绿色 55 | Offset centerD = Offset(-len, len); 56 | drawItem(canvas, centerD, colors[3]); 57 | } 58 | 59 | void drawItem( 60 | Canvas canvas, 61 | Offset center, 62 | Color color, 63 | ) { 64 | Rect rect = 65 | Rect.fromCenter(center: center, width: itemWidth, height: itemWidth); 66 | canvas.drawRRect( 67 | RRect.fromRectAndRadius(rect, const Radius.circular(5)), 68 | _paint..color = color, 69 | ); 70 | } 71 | 72 | @override 73 | bool shouldRepaint(covariant RotateLoadingPainter oldDelegate) => 74 | oldDelegate.itemWidth != itemWidth; 75 | } 76 | -------------------------------------------------------------------------------- /lib/06_loading/02_rotate/02_anim_01/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'rotate_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | RotateLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/02_rotate/03_anim_last/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'rotate_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | RotateLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/03_cross/01_cross_single/cross_loading.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class CrossLoading extends StatefulWidget { 6 | final double size; 7 | 8 | const CrossLoading({Key key, this.size = 100}) : super(key: key); 9 | 10 | @override 11 | _CrossLoadingState createState() => _CrossLoadingState(); 12 | } 13 | 14 | class _CrossLoadingState extends State 15 | with SingleTickerProviderStateMixin { 16 | @override 17 | Widget build(BuildContext context) { 18 | return CustomPaint( 19 | size: Size(widget.size, widget.size), 20 | painter: CrossLoadingPainter(), 21 | ); 22 | } 23 | } 24 | 25 | class CrossLoadingPainter extends CustomPainter { 26 | CrossLoadingPainter({this.itemWidth = 33}); 27 | 28 | final double itemWidth; 29 | final Paint _paint = Paint(); 30 | 31 | @override 32 | void paint(Canvas canvas, Size size) { 33 | canvas.drawRect( 34 | Offset.zero & size, Paint()..color = Colors.grey.withAlpha(11)); 35 | canvas.translate(size.width / 2, size.height / 2); 36 | 37 | final double offset = -size.height / 2 + itemWidth / sqrt(2); 38 | drawDiamond(canvas, offset,Color(0xffF44336)); 39 | } 40 | 41 | void drawDiamond(Canvas canvas,double offset, Color color) { 42 | canvas.save(); 43 | canvas.translate(0, offset); 44 | canvas.rotate(45 / 180 * pi); 45 | 46 | canvas.drawRect( 47 | Rect.fromCenter( 48 | center: Offset.zero, width: itemWidth, height: itemWidth), 49 | _paint..color = color); 50 | canvas.restore(); 51 | } 52 | 53 | @override 54 | bool shouldRepaint(covariant CrossLoadingPainter oldDelegate) => 55 | oldDelegate.itemWidth != itemWidth; 56 | } 57 | -------------------------------------------------------------------------------- /lib/06_loading/03_cross/01_cross_single/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'cross_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CrossLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/03_cross/02_cross_static/cross_loading.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class CrossLoading extends StatefulWidget { 6 | final double size; 7 | 8 | const CrossLoading({Key key, this.size = 100}) : super(key: key); 9 | 10 | @override 11 | _CrossLoadingState createState() => _CrossLoadingState(); 12 | } 13 | 14 | class _CrossLoadingState extends State 15 | with SingleTickerProviderStateMixin { 16 | @override 17 | Widget build(BuildContext context) { 18 | return CustomPaint( 19 | size: Size(widget.size, widget.size), 20 | painter: CrossLoadingPainter(), 21 | ); 22 | } 23 | } 24 | 25 | class CrossLoadingPainter extends CustomPainter { 26 | CrossLoadingPainter({this.itemWidth = 33}); 27 | 28 | final List colors = const [ 29 | Color(0xffF44336), Color(0xff5C6BC0), Color(0xffFFB74D), Color(0xff8BC34A), 30 | ]; 31 | 32 | final double itemWidth; 33 | final Paint _paint = Paint(); 34 | 35 | @override 36 | void paint(Canvas canvas, Size size) { 37 | canvas.drawRect( 38 | Offset.zero & size, Paint()..color = Colors.grey.withAlpha(11)); 39 | canvas.translate(size.width / 2, size.height / 2); 40 | 41 | final double offset = -size.height / 2 + itemWidth / sqrt(2); 42 | 43 | drawDiamond(canvas, offset, colors[0], true); 44 | drawDiamond(canvas, -offset, colors[1], true); 45 | drawDiamond(canvas, -offset, colors[2], false); 46 | drawDiamond(canvas, offset, colors[3], false); 47 | } 48 | 49 | void drawDiamond(Canvas canvas, double offset,Color color,bool vertical,) { 50 | canvas.save(); 51 | if (vertical) { 52 | canvas.translate(0, offset); 53 | } else { 54 | canvas.translate(offset, 0); 55 | } 56 | canvas.rotate(45 / 180 * pi); 57 | canvas.drawRect( 58 | Rect.fromCenter(center: Offset.zero, width: itemWidth, height: itemWidth), 59 | _paint..color = color); 60 | canvas.restore(); 61 | } 62 | 63 | @override 64 | bool shouldRepaint(covariant CrossLoadingPainter oldDelegate) => 65 | oldDelegate.itemWidth != itemWidth; 66 | 67 | } 68 | -------------------------------------------------------------------------------- /lib/06_loading/03_cross/02_cross_static/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'cross_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CrossLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/03_cross/03_cross_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'cross_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | CrossLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/04_ovel/01_oval_single/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'oval_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | OvalLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/04_ovel/01_oval_single/oval_loading.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class OvalLoading extends StatefulWidget { 6 | final double size; 7 | 8 | const OvalLoading({Key key, this.size = 150}) : super(key: key); 9 | 10 | @override 11 | _OvalLoadingState createState() => _OvalLoadingState(); 12 | } 13 | 14 | class _OvalLoadingState extends State 15 | with SingleTickerProviderStateMixin { 16 | AnimationController _ctrl; 17 | Animation animation; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | _ctrl = AnimationController( 23 | vsync: this, 24 | duration: Duration(seconds: 2), 25 | ); 26 | animation = Tween(begin: -pi, end: pi).animate(_ctrl); 27 | } 28 | 29 | @override 30 | void dispose() { 31 | _ctrl.dispose(); 32 | super.dispose(); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return GestureDetector( 38 | onTap: () => _ctrl.repeat(), 39 | child: CustomPaint( 40 | size: Size(widget.size, widget.size), 41 | painter: OvalLoadingPainter(animation), 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class OvalLoadingPainter extends CustomPainter { 48 | Animation animation; 49 | 50 | OvalLoadingPainter(this.animation, {this.radius = 15, this.a = 0.4}) 51 | : super(repaint: animation); 52 | 53 | final Paint _paint = Paint(); 54 | final double radius; 55 | final double a; 56 | 57 | @override 58 | void paint(Canvas canvas, Size size) { 59 | canvas.drawRect( 60 | Offset.zero & size, Paint()..color = Colors.grey.withAlpha(11)); 61 | 62 | double zoneSize = size.shortestSide / 2; 63 | canvas.translate(size.width / 2, size.height / 2); 64 | 65 | canvas.drawOval( 66 | Rect.fromCenter( 67 | center: Offset.zero, 68 | width: zoneSize * 2 - radius, 69 | height: zoneSize * a * 2 - radius), 70 | Paint()..style = PaintingStyle.stroke, 71 | ); 72 | 73 | double x = (zoneSize - radius) * f(animation.value); 74 | double y = (zoneSize - radius) * g(animation.value); 75 | 76 | canvas.drawCircle(Offset(x, y), radius, _paint..color = Color(0xffF44336)); 77 | } 78 | 79 | double f(double t) => cos(t); 80 | 81 | double g(double t) => a * sin(t); 82 | 83 | @override 84 | bool shouldRepaint(covariant OvalLoadingPainter oldDelegate) => 85 | oldDelegate.a != a || oldDelegate.animation != animation; 86 | } 87 | -------------------------------------------------------------------------------- /lib/06_loading/04_ovel/02_sin_single/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'oval_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | OvalLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/06_loading/04_ovel/02_sin_single/oval_loading.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class OvalLoading extends StatefulWidget { 6 | final double size; 7 | 8 | const OvalLoading({Key key, this.size = 150}) : super(key: key); 9 | 10 | @override 11 | _OvalLoadingState createState() => _OvalLoadingState(); 12 | } 13 | 14 | class _OvalLoadingState extends State 15 | with SingleTickerProviderStateMixin { 16 | AnimationController _ctrl; 17 | Animation animation; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | _ctrl = AnimationController( 23 | vsync: this, 24 | duration: Duration(seconds: 2), 25 | ); 26 | animation = Tween(begin: -pi, end: pi).animate(_ctrl); 27 | } 28 | 29 | @override 30 | void dispose() { 31 | _ctrl.dispose(); 32 | super.dispose(); 33 | } 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | return GestureDetector( 38 | onTap: () => _ctrl.repeat(reverse: true), 39 | child: CustomPaint( 40 | size: Size(widget.size, widget.size), 41 | painter: OvalLoadingPainter(animation), 42 | ), 43 | ); 44 | } 45 | } 46 | 47 | class OvalLoadingPainter extends CustomPainter { 48 | Animation animation; 49 | 50 | OvalLoadingPainter(this.animation, {this.radius = 15, this.a = 0.4}) 51 | : super(repaint: animation); 52 | 53 | final Paint _paint = Paint(); 54 | final double radius; 55 | final double a; 56 | 57 | @override 58 | void paint(Canvas canvas, Size size) { 59 | canvas.drawRect( 60 | Offset.zero & size, Paint()..color = Colors.grey.withAlpha(11)); 61 | 62 | double zoneSize = size.shortestSide / 2; 63 | canvas.translate(size.width / 2, size.height / 2); 64 | 65 | double x = (zoneSize - radius)/pi * f(animation.value); 66 | double y = (zoneSize - radius)/2 * g(animation.value); 67 | 68 | canvas.drawCircle(Offset(x, y), radius, _paint..color = Color(0xffF44336)); 69 | } 70 | 71 | double f(double t) => t; 72 | double g(double t) => sin(t); 73 | 74 | @override 75 | bool shouldRepaint(covariant OvalLoadingPainter oldDelegate) => 76 | oldDelegate.a != a || oldDelegate.animation != animation; 77 | } 78 | -------------------------------------------------------------------------------- /lib/06_loading/04_ovel/03_oval_last/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'oval_loading.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | // backgroundColor: Colors.black, 24 | body: Center( 25 | child: Wrap( 26 | spacing: 50, 27 | children:[ 28 | OvalLoading() 29 | ] , 30 | ), 31 | )) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/07_animated_widget/01_RotationTransition/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State 34 | with SingleTickerProviderStateMixin { 35 | AnimationController _ctrl; 36 | Animation animation; 37 | 38 | @override 39 | void initState() { 40 | super.initState(); 41 | _ctrl = AnimationController( 42 | vsync: this, 43 | duration: const Duration(seconds: 2), 44 | ); 45 | animation = CurveTween(curve: Curves.linear).animate(_ctrl); 46 | } 47 | 48 | @override 49 | void dispose() { 50 | _ctrl.dispose(); 51 | super.dispose(); 52 | } 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return GestureDetector( 57 | onTap: () => _ctrl.forward(from: 0), 58 | child: Container( 59 | color: Colors.grey.withAlpha(22), 60 | width: 100, 61 | height: 100, 62 | child: RotationTransition( 63 | turns: animation, 64 | child: _buildChild(), 65 | ), 66 | ), 67 | ); 68 | } 69 | 70 | Widget _buildChild() => const Icon( 71 | Icons.camera_outlined, 72 | color: Colors.green, 73 | size: 60, 74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /lib/07_animated_widget/02_ScaleTransition/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State 34 | with SingleTickerProviderStateMixin { 35 | AnimationController _ctrl; 36 | Animation animation; 37 | 38 | @override 39 | void initState() { 40 | super.initState(); 41 | _ctrl = AnimationController( 42 | vsync: this, 43 | duration: const Duration(seconds: 2), 44 | ); 45 | animation = Tween(begin: 0.3, end: 1.0) 46 | .chain(CurveTween(curve: Curves.ease)) 47 | .animate(_ctrl); 48 | } 49 | 50 | @override 51 | void dispose() { 52 | _ctrl.dispose(); 53 | super.dispose(); 54 | } 55 | 56 | @override 57 | Widget build(BuildContext context) { 58 | return GestureDetector( 59 | onTap: () => _ctrl.forward(from: 0), 60 | child: Container( 61 | color: Colors.grey.withAlpha(22), 62 | width: 100, 63 | height: 100, 64 | child: ScaleTransition( 65 | scale: animation, 66 | child: _buildChild(), 67 | ), 68 | )); 69 | } 70 | 71 | Widget _buildChild() => const Icon( 72 | Icons.camera_outlined, 73 | color: Colors.green, 74 | size: 60, 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /lib/07_animated_widget/04_AlignTransition/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State 34 | with SingleTickerProviderStateMixin { 35 | AnimationController _ctrl; 36 | Animation animation; 37 | 38 | @override 39 | void initState() { 40 | super.initState(); 41 | _ctrl = AnimationController( 42 | vsync: this, 43 | duration: const Duration(seconds: 2), 44 | ); 45 | 46 | animation = AlignmentTween( 47 | begin: Alignment.center, 48 | end: Alignment.bottomRight, 49 | ).chain(CurveTween(curve: Curves.ease)).animate(_ctrl); 50 | } 51 | 52 | @override 53 | void dispose() { 54 | _ctrl.dispose(); 55 | super.dispose(); 56 | } 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return GestureDetector( 61 | onTap: () => _ctrl.forward(from: 0), 62 | child: Container( 63 | color: Colors.grey.withAlpha(22), 64 | width: 200, 65 | height: 100, 66 | child: AlignTransition( 67 | alignment: animation, 68 | child: _buildChild(), 69 | ), 70 | )); 71 | } 72 | 73 | Widget _buildChild() => const Icon( 74 | Icons.accessible_forward_sharp, 75 | color: Colors.green, 76 | size: 25, 77 | ); 78 | } -------------------------------------------------------------------------------- /lib/09_implicitly_animated_widget/01_AnimatedOpacity/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State { 34 | final double beginOpacity = 1.0; 35 | final double endOpacity = 0; 36 | 37 | double _opacity; 38 | 39 | @override 40 | void initState() { 41 | super.initState(); 42 | _opacity = beginOpacity; 43 | } 44 | 45 | bool get selected => _opacity == 0; 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return Wrap( 50 | direction: Axis.vertical, 51 | crossAxisAlignment: WrapCrossAlignment.center, 52 | children: [ 53 | Switch( 54 | value: selected, 55 | onChanged: onChanged, 56 | ), 57 | Container( 58 | color: Colors.grey.withAlpha(22), 59 | width: 100, 60 | height: 100, 61 | child: buildAnimatedOpacity(), 62 | ), 63 | ], 64 | ); 65 | } 66 | 67 | Widget buildAnimatedOpacity() => 68 | AnimatedOpacity( 69 | duration: const Duration(seconds: 1), 70 | curve: Curves.fastOutSlowIn, 71 | opacity: _opacity, 72 | onEnd: onEnd, 73 | child: _buildChild(), 74 | ); 75 | 76 | void onChanged(bool value) { 77 | setState(() { 78 | _opacity = value ? endOpacity : beginOpacity; 79 | }); 80 | } 81 | 82 | void onEnd() { 83 | print('End'); 84 | } 85 | 86 | Widget _buildChild() => 87 | const Icon( 88 | Icons.camera_outlined, 89 | color: Colors.green, 90 | size: 60, 91 | ); 92 | } 93 | -------------------------------------------------------------------------------- /lib/09_implicitly_animated_widget/03_AnimatedAlign/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State { 34 | final Alignment startAlignment = Alignment.center; 35 | final Alignment endAlignment = Alignment.bottomRight; 36 | 37 | Alignment _alignment; 38 | 39 | @override 40 | void initState() { 41 | super.initState(); 42 | _alignment = startAlignment; 43 | } 44 | 45 | bool get selected => _alignment == endAlignment; 46 | 47 | @override 48 | Widget build(BuildContext context) { 49 | return Wrap( 50 | direction: Axis.vertical, 51 | crossAxisAlignment: WrapCrossAlignment.center, 52 | children: [ 53 | Switch( 54 | value: selected, 55 | onChanged: onChanged, 56 | ), 57 | Container( 58 | width: 200, 59 | height: 100, 60 | alignment: Alignment.center, 61 | color: Colors.grey.withAlpha(22), 62 | child: buildAnim()) 63 | ], 64 | ); 65 | } 66 | 67 | Widget buildAnim() => AnimatedAlign( 68 | duration: Duration(seconds: 1), 69 | curve: Curves.fastOutSlowIn, 70 | alignment: _alignment, 71 | onEnd: onEnd, 72 | child: const Icon( 73 | Icons.accessible_forward_sharp, 74 | color: Colors.green, 75 | size: 25, 76 | ), 77 | ); 78 | 79 | 80 | void onChanged(bool value) { 81 | setState(() { 82 | _alignment = value ? endAlignment : startAlignment; 83 | }); 84 | } 85 | 86 | void onEnd() { 87 | print('End'); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/09_implicitly_animated_widget/05_TweenAnimationBuilder/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State { 34 | bool _selected = false; 35 | 36 | Color color1 = Colors.red; 37 | Color color2 = Colors.orange; 38 | 39 | @override 40 | Widget build(BuildContext context) { 41 | return Wrap( 42 | direction: Axis.vertical, 43 | crossAxisAlignment: WrapCrossAlignment.center, 44 | children: [ 45 | Switch( 46 | value: _selected, 47 | onChanged: onChanged, 48 | ), 49 | buildAnim() 50 | ], 51 | ); 52 | } 53 | 54 | Widget buildAnim() => TweenAnimationBuilder( 55 | tween: ColorTween(begin: Colors.blue, end: _selected?color1:color2), 56 | duration: Duration(seconds: 1), 57 | builder: (_, Color color, Widget child) => Container( 58 | width: 60, 59 | height: 60, 60 | child: child, 61 | decoration: BoxDecoration( 62 | color: color, 63 | borderRadius: BorderRadius.circular(8), 64 | ), 65 | ), 66 | child: _buildChild(), 67 | ); 68 | 69 | Widget _buildChild() => const Icon( 70 | Icons.camera_outlined, 71 | size: 30, 72 | color: Colors.white, 73 | ); 74 | 75 | void onChanged(bool value) { 76 | setState(() { 77 | _selected = !_selected; 78 | }); 79 | } 80 | 81 | void onEnd() { 82 | print('End'); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/11_other/01_painter/01_AnimatedIcon/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State with SingleTickerProviderStateMixin{ 34 | AnimationController _ctrl; 35 | 36 | @override 37 | void initState() { 38 | super.initState(); 39 | _ctrl = AnimationController( 40 | vsync: this, 41 | duration: const Duration(seconds: 1), 42 | ); 43 | } 44 | 45 | @override 46 | void dispose() { 47 | _ctrl.dispose(); 48 | super.dispose(); 49 | } 50 | 51 | @override 52 | Widget build(BuildContext context) { 53 | return GestureDetector( 54 | onTap: () => _ctrl.forward(from: 0), 55 | child: AnimatedIcon( 56 | size: 50, 57 | color: Colors.green, 58 | icon: AnimatedIcons.arrow_menu, 59 | progress: _ctrl, 60 | ), 61 | ); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /lib/11_other/01_painter/02_CupertinoActivityIndicator/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: AnimDemo(), 25 | ))); 26 | } 27 | } 28 | 29 | class AnimDemo extends StatefulWidget { 30 | @override 31 | _AnimDemoState createState() => _AnimDemoState(); 32 | } 33 | 34 | class _AnimDemoState extends State with SingleTickerProviderStateMixin{ 35 | bool _animating = true; 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Wrap( 40 | direction: Axis.vertical, 41 | crossAxisAlignment: WrapCrossAlignment.center, 42 | children: [ 43 | Switch( 44 | value: _animating, 45 | onChanged: onChanged, 46 | ), 47 | CupertinoActivityIndicator( 48 | animating: _animating, 49 | radius: 20, 50 | ), 51 | ], 52 | ); 53 | } 54 | 55 | void onChanged(bool value) { 56 | setState(() { 57 | _animating = !_animating; 58 | }); 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /lib/11_other/02_other/01_AnimatedCrossFade/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() { 5 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 6 | SystemChrome.setPreferredOrientations(// 使设备横屏显示 7 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 8 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 9 | runApp(MyApp()); 10 | } 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | title: 'Flutter Demo', 18 | theme: ThemeData( 19 | primarySwatch: Colors.blue, 20 | ), 21 | home: Scaffold( 22 | body: Center( 23 | child: AnimDemo(), 24 | ))); 25 | } 26 | } 27 | 28 | class AnimDemo extends StatefulWidget { 29 | @override 30 | _AnimDemoState createState() => _AnimDemoState(); 31 | } 32 | 33 | class _AnimDemoState extends State { 34 | var _crossFadeState = CrossFadeState.showFirst; 35 | 36 | bool get isFirst => _crossFadeState == CrossFadeState.showFirst; 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | return Wrap( 41 | direction: Axis.vertical, 42 | crossAxisAlignment: WrapCrossAlignment.center, 43 | children: [ 44 | Switch( 45 | value: isFirst, 46 | onChanged: _onChanged, 47 | ), 48 | AnimatedCrossFade( 49 | firstCurve: Curves.easeInCirc, 50 | secondCurve: Curves.easeInToLinear, 51 | sizeCurve: Curves.bounceOut, 52 | firstChild: buildFirstChild(), 53 | secondChild: buildSecondChild(), 54 | duration: Duration(milliseconds: 1000), 55 | crossFadeState: _crossFadeState, 56 | ), 57 | ], 58 | ); 59 | } 60 | 61 | Widget buildFirstChild() => Container( 62 | height: 60, 63 | width: 60, 64 | color: Colors.grey.withAlpha(22), 65 | alignment: Alignment.center, 66 | child: const FlutterLogo( 67 | size: 40, 68 | ), 69 | ); 70 | 71 | Widget buildSecondChild() => Image.asset( 72 | "assets/images/icon_head.jpg", 73 | height: 100, 74 | width: 100, 75 | ); 76 | 77 | void _onChanged(bool value) { 78 | setState(() { 79 | _crossFadeState = 80 | value ? CrossFadeState.showFirst : CrossFadeState.showSecond; 81 | }); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/11_other/04_router/01_common/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() { 4 | runApp(MyApp()); 5 | } 6 | 7 | class MyApp extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | debugShowCheckedModeBanner: false, 12 | title: 'Flutter Demo', 13 | theme: ThemeData( 14 | primarySwatch: Colors.blue, 15 | ), 16 | home: GreenPage()); 17 | } 18 | } 19 | 20 | class GreenPage extends StatelessWidget { 21 | const GreenPage({Key key}) : super(key: key); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return Scaffold( 26 | backgroundColor: Colors.green, 27 | appBar: AppBar( 28 | title: const Text('GreenPage'), 29 | actions: [ 30 | IconButton( 31 | onPressed: () => _toRed(context), 32 | icon: Icon(Icons.navigate_next), 33 | ) 34 | ], 35 | ), 36 | ); 37 | } 38 | 39 | void _toRed(BuildContext context) { 40 | Navigator.of(context).push( 41 | MaterialPageRoute(builder: (ctx) => RedPage()), 42 | ); 43 | } 44 | } 45 | 46 | class RedPage extends StatelessWidget { 47 | const RedPage({Key key}) : super(key: key); 48 | 49 | @override 50 | Widget build(BuildContext context) { 51 | return Scaffold( 52 | backgroundColor: Colors.red, 53 | appBar: AppBar( 54 | title: const Text('RedPage'), 55 | ), 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/11_other/04_router/02_anim/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() { 4 | runApp(MyApp()); 5 | } 6 | 7 | class MyApp extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | debugShowCheckedModeBanner: false, 12 | title: 'Flutter Demo', 13 | theme: ThemeData( 14 | primarySwatch: Colors.blue, 15 | ), 16 | home: GreenPage()); 17 | } 18 | } 19 | 20 | class GreenPage extends StatelessWidget { 21 | const GreenPage({Key key}) : super(key: key); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return Scaffold( 26 | backgroundColor: Colors.green, 27 | appBar: AppBar( 28 | title: const Text('GreenPage'), 29 | actions: [ 30 | IconButton( 31 | onPressed: () => _toRed(context), 32 | icon: Icon(Icons.navigate_next), 33 | ) 34 | ], 35 | ), 36 | ); 37 | } 38 | 39 | void _toRed(BuildContext context) { 40 | Navigator.of(context).push( 41 | PageRouteBuilder( 42 | pageBuilder: (ctx, a1, a2) => RedPage(), 43 | transitionDuration: const Duration(milliseconds: 300), 44 | reverseTransitionDuration: const Duration(milliseconds: 300), 45 | transitionsBuilder: _buildTransitions), 46 | ); 47 | } 48 | 49 | Widget _buildTransitions( 50 | BuildContext context, 51 | Animation animation, 52 | Animation secondaryAnimation, 53 | Widget child, 54 | ) { 55 | return SlideTransition( 56 | position: Tween( 57 | begin: const Offset(1.0, 0), 58 | end: Offset.zero, 59 | ).animate(animation), 60 | child: FadeTransition( 61 | opacity: Tween( 62 | begin: 0.5, 63 | end: 1.0) 64 | .animate(animation), 65 | child: child, 66 | ), 67 | ); 68 | } 69 | } 70 | 71 | 72 | class RedPage extends StatelessWidget { 73 | const RedPage({Key key}) : super(key: key); 74 | 75 | @override 76 | Widget build(BuildContext context) { 77 | return Scaffold( 78 | backgroundColor: Colors.red, 79 | appBar: AppBar( 80 | title: const Text('RedPage'), 81 | ), 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/14/debug/circle_anim.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CircleAnim extends StatefulWidget { 4 | @override 5 | _CircleAnimState createState() => _CircleAnimState(); 6 | } 7 | 8 | class _CircleAnimState extends State 9 | with SingleTickerProviderStateMixin { 10 | AnimationController _ctrl; 11 | 12 | @override 13 | void initState() { 14 | super.initState(); 15 | _ctrl = AnimationController( 16 | vsync: this, 17 | duration: const Duration(milliseconds: 1000), 18 | )..addListener(() { 19 | print("------${_ctrl.value}----${DateTime.now().toIso8601String()}----------"); 20 | }); 21 | } 22 | 23 | @override 24 | void dispose() { 25 | _ctrl.dispose(); 26 | super.dispose(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return GestureDetector( 32 | onTap: _startAnim, 33 | child:Container( 34 | width: 60, 35 | height: 60, 36 | color: Colors.green, 37 | )); 38 | } 39 | 40 | Color get color => Color.lerp(Colors.blue, Colors.red, _ctrl.value); 41 | 42 | Widget _buildByAnim(_, __) => Container( 43 | width: 80, 44 | height: 80, 45 | decoration: BoxDecoration(color: color, shape: BoxShape.circle), 46 | ); 47 | 48 | void _startAnim() { 49 | _ctrl.forward(from: 0); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/14/debug/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'circle_anim.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: CircleAnim(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'ticker_demo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: TickerDemo(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker/ticker_demo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/scheduler.dart'; 3 | 4 | class TickerDemo extends StatefulWidget { 5 | @override 6 | _TickerDemoState createState() => _TickerDemoState(); 7 | } 8 | 9 | class _TickerDemoState extends State { 10 | Ticker _ticker; 11 | 12 | @override 13 | void initState() { 14 | super.initState(); 15 | // SchedulerBinding.instance.scheduleFrameCallback(_tick); 16 | _ticker = Ticker(_tick); 17 | } 18 | 19 | void _tick(Duration elapsed) { 20 | print('----elapsed:$elapsed---${TimeOfDay.now()}------------'); 21 | } 22 | 23 | @override 24 | void dispose() { 25 | _ticker.dispose(); 26 | super.dispose(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return GestureDetector( 32 | onTap: _startTicker, 33 | child: Container( 34 | width: 60, 35 | height: 60, 36 | color: Colors.green, 37 | )); 38 | } 39 | 40 | void _startTicker() { 41 | 42 | if (_ticker.isTicking) { 43 | _ticker.stop(); 44 | } else { 45 | _ticker.start().then((v) { 46 | print('start finish!'); 47 | }); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker_muted/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'ticker_demo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: TickerDemo(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker_muted/ticker_demo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/scheduler.dart'; 3 | 4 | class TickerDemo extends StatefulWidget { 5 | @override 6 | _TickerDemoState createState() => _TickerDemoState(); 7 | } 8 | 9 | class _TickerDemoState extends State { 10 | Ticker _ticker; 11 | 12 | @override 13 | void initState() { 14 | super.initState(); 15 | // SchedulerBinding.instance.scheduleFrameCallback(_tick); 16 | _ticker = Ticker(_tick)..start(); 17 | } 18 | 19 | void _tick(Duration elapsed) { 20 | print('----elapsed:$elapsed---${DateTime.now().toIso8601String()}------------'); 21 | } 22 | 23 | @override 24 | void dispose() { 25 | _ticker.dispose(); 26 | super.dispose(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return GestureDetector( 32 | onTap: _startTicker, 33 | child: Container( 34 | width: 60, 35 | height: 60, 36 | color: Colors.green, 37 | )); 38 | } 39 | 40 | void _startTicker() { 41 | if (_ticker.muted) { 42 | _ticker.muted = false; 43 | } else { 44 | _ticker.muted = true; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker_provider/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'ticker_demo.dart'; 4 | 5 | void main() { 6 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 7 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 8 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 9 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 10 | runApp(MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | @override 15 | Widget build(BuildContext context) { 16 | return MaterialApp( 17 | debugShowCheckedModeBanner: false, 18 | title: 'Flutter Demo', 19 | theme: ThemeData( 20 | primarySwatch: Colors.blue, 21 | ), 22 | home: Scaffold( 23 | body: Center( 24 | child: TickerDemo(), 25 | )) 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/15_ticker/ticker_provider/ticker_demo.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class TickerDemo extends StatefulWidget { 4 | @override 5 | _TickerDemoState createState() => _TickerDemoState(); 6 | } 7 | 8 | class _TickerDemoState extends State with SingleTickerProviderStateMixin { 9 | AnimationController _ctrlA; 10 | 11 | final Duration animDuration = const Duration(milliseconds: 2000); 12 | 13 | @override 14 | void initState() { 15 | super.initState(); 16 | _ctrlA = AnimationController( 17 | value: 0.4, 18 | vsync: this, 19 | duration: animDuration, 20 | ); 21 | 22 | 23 | } 24 | 25 | @override 26 | void dispose() { 27 | _ctrlA.dispose(); 28 | 29 | super.dispose(); 30 | } 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return GestureDetector( 35 | onTap: _start, 36 | child: Container( 37 | width: 60, 38 | height: 60, 39 | color: Colors.green, 40 | )); 41 | } 42 | 43 | void _start() {} 44 | } 45 | -------------------------------------------------------------------------------- /lib/16_clock/01/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/02/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/03/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/04_stack/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/05_last/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/01/clock_fx.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | import 'particle.dart'; 7 | 8 | 9 | final Color transparent = Color.fromARGB(0, 0, 0, 0); 10 | 11 | abstract class ClockFx with ChangeNotifier { 12 | /// The available canvas width for the FX. 13 | double width; 14 | 15 | /// The available canvas height for the FX. 16 | double height; 17 | 18 | /// The minimum value of [width] and [height]. 19 | double sizeMin; 20 | 21 | /// The center of the canvas. 22 | Offset center; 23 | 24 | /// The area from wich to spawn new particles. 25 | Rect spawnArea; 26 | 27 | /// The colors used for painting. 28 | // Palette palette; 29 | 30 | /// All the FX's particles. 31 | List particles; 32 | 33 | /// The maximum number of particles. 34 | int numParticles; 35 | 36 | /// Date and time used for rendering time-specific effects. 37 | DateTime time; 38 | 39 | ClockFx({ 40 | @required Size size, 41 | @required DateTime time, 42 | this.numParticles = 5000, 43 | }) { 44 | this.time = time; 45 | particles = List.filled(numParticles, null); 46 | setSize(size); 47 | } 48 | 49 | /// Initializes the particle effect by resetting all the particles and assigning a random color from the palette. 50 | void init() { 51 | // if (palette == null) return; 52 | for (int i = 0; i < numParticles; i++) { 53 | // var color = Rnd.getItem(palette.components); 54 | particles[i] = Particle(color:Colors.black ); 55 | resetParticle(i); 56 | } 57 | } 58 | 59 | /// Sets the time used for time-specific effects. 60 | void setTime(DateTime time) { 61 | this.time = time; 62 | } 63 | 64 | /// Sets the canvas size and updates dependent values. 65 | void setSize(Size size) { 66 | width = size.width; 67 | height = size.height; 68 | sizeMin = min(width, height); 69 | center = Offset(width / 2, height / 2); 70 | spawnArea = Rect.fromLTRB( 71 | center.dx - sizeMin / 100, 72 | center.dy - sizeMin / 100, 73 | center.dx + sizeMin / 100, 74 | center.dy + sizeMin / 100, 75 | ); 76 | init(); 77 | } 78 | 79 | /// Resets a particle's values. 80 | Particle resetParticle(int i) { 81 | Particle p = particles[i]; 82 | p.size = p.a = p.vx = p.vy = p.life = p.lifeLeft = 0; 83 | p.x = center.dx; 84 | p.y = center.dy; 85 | return p; 86 | } 87 | 88 | void tick(Duration duration) { 89 | notifyListeners(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/01/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/01/particle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | class Particle { 7 | 8 | double x; // x 坐标 9 | double y; // y 坐标 10 | double vx; // x 速度 11 | double vy; // y 速度 12 | double a; // 发射弧度 13 | double dist; // 距离画布中心的长度 14 | double distFrac;// 距离画布中心的百分比 15 | double size;// 粒子大小 16 | double life; // 粒子寿命 17 | double lifeLeft; // 粒子剩余寿命 18 | bool isFilled; // 是否填充 19 | Color color; // 颜色 20 | int distribution; // 描述 21 | 22 | 23 | Particle({ 24 | this.x = 0, 25 | this.y = 0, 26 | this.a = 0, 27 | this.vx = 0, 28 | this.vy = 0, 29 | this.dist = 0, 30 | this.distFrac = 0, 31 | this.size = 0, 32 | this.life = 0, 33 | this.lifeLeft = 0, 34 | this.isFilled = false, 35 | this.color = Colors.blueAccent, 36 | this.distribution = 0, 37 | }); 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/01/utils/rnd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | 4 | class Rnd { 5 | static int _seed = DateTime.now().millisecondsSinceEpoch; 6 | static Random random = Random(_seed); 7 | 8 | static set seed(int val) => random = Random(_seed = val); 9 | static int get seed => _seed; 10 | 11 | /// Gets the next double. 12 | static get ratio => random.nextDouble(); 13 | 14 | /// Gets a random int between [min] and [max]. 15 | static int getInt(int min, int max) { 16 | return min + random.nextInt(max - min); 17 | } 18 | 19 | /// Gets a random double between [min] and [max]. 20 | static double getDouble(double min, double max) { 21 | return min + random.nextDouble() * (max - min); 22 | } 23 | 24 | /// Gets a random boolean with chance [chance]. 25 | static bool getBool([double chance = 0.5]) { 26 | return random.nextDouble() < chance; 27 | } 28 | 29 | /// Randomize the positions of items in a list. 30 | static List shuffle(List list) { 31 | for (int i = 0, l = list.length; i < l; i++) { 32 | int j = random.nextInt(l); 33 | if (j == i) { 34 | continue; 35 | } 36 | dynamic item = list[j]; 37 | list[j] = list[i]; 38 | list[i] = item; 39 | } 40 | return list; 41 | } 42 | 43 | /// Randomly selects an item from a list. 44 | static dynamic getItem(List list) { 45 | return list[random.nextInt(list.length)]; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/02/clock_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/scheduler.dart'; 7 | 8 | import 'clock_fx.dart'; 9 | 10 | /// create by 张风捷特烈 on 2021/2/7 11 | /// contact me by email 1981462002@qq.com 12 | /// 说明: 13 | 14 | class ClockWidget extends StatefulWidget { 15 | final double radius; 16 | 17 | const ClockWidget({Key key, this.radius = 100}) : super(key: key); 18 | 19 | @override 20 | _ClockWidgetState createState() => _ClockWidgetState(); 21 | } 22 | 23 | class _ClockWidgetState extends State 24 | with SingleTickerProviderStateMixin { 25 | Ticker _ticker; 26 | ClockFx _fx; 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | _ticker = createTicker(_tick)..start(); 32 | _fx = ClockFx( 33 | size: Size(widget.radius * 2, widget.radius * 2), 34 | time: DateTime.now(), 35 | ); 36 | } 37 | 38 | @override 39 | void dispose() { 40 | _ticker.dispose(); 41 | _fx.dispose(); 42 | super.dispose(); 43 | } 44 | 45 | void _tick(Duration duration) { 46 | _fx.tick(duration); 47 | if (_fx.time.second != DateTime.now().second) { 48 | _fx.setTime(DateTime.now()); 49 | } 50 | } 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return CustomPaint( 55 | size: Size(widget.radius * 2, widget.radius * 2), 56 | painter: ClockFxPainter(fx: _fx), 57 | ); 58 | } 59 | } 60 | 61 | /// Alpha value for noise particles. 62 | const double noiseAlpha = 160; 63 | 64 | class ClockFxPainter extends CustomPainter { 65 | final ClockFx fx; 66 | 67 | ClockFxPainter({@required this.fx}) : super(repaint: fx); 68 | 69 | @override 70 | void paint(Canvas canvas, Size size) { 71 | fx.particles.forEach((p) { 72 | double a; 73 | a = max(0.0, (p.distFrac - .13) / p.distFrac) * 255; 74 | a = min(a, min(noiseAlpha, p.lifeLeft * 3 * 255)); 75 | int alpha = a.floor(); 76 | 77 | Paint circlePaint = Paint() 78 | ..style = PaintingStyle.fill 79 | ..color = p.color.withAlpha(alpha); 80 | 81 | canvas.drawCircle(Offset(p.x, p.y), p.size, circlePaint); 82 | }); 83 | } 84 | 85 | @override 86 | bool shouldRepaint(covariant ClockFxPainter oldDelegate) => 87 | oldDelegate.fx != fx; 88 | } 89 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/02/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/02/particle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | class Particle { 7 | 8 | double x; // x 坐标 9 | double y; // y 坐标 10 | double vx; // x 速度 11 | double vy; // y 速度 12 | double a; // 发射弧度 13 | double dist; // 距离画布中心的长度 14 | double distFrac;// 距离画布中心的百分比 15 | double size;// 粒子大小 16 | double life; // 粒子寿命 17 | double lifeLeft; // 粒子剩余寿命 18 | bool isFilled; // 是否填充 19 | Color color; // 颜色 20 | int distribution; // 分配情况 21 | 22 | 23 | Particle({ 24 | this.x = 0, 25 | this.y = 0, 26 | this.a = 0, 27 | this.vx = 0, 28 | this.vy = 0, 29 | this.dist = 0, 30 | this.distFrac = 0, 31 | this.size = 0, 32 | this.life = 0, 33 | this.lifeLeft = 0, 34 | this.isFilled = false, 35 | this.color = Colors.blueAccent, 36 | this.distribution = 0, 37 | }); 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/02/utils/rnd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | 4 | class Rnd { 5 | static int _seed = DateTime.now().millisecondsSinceEpoch; 6 | static Random random = Random(_seed); 7 | 8 | static set seed(int val) => random = Random(_seed = val); 9 | static int get seed => _seed; 10 | 11 | /// Gets the next double. 12 | static get ratio => random.nextDouble(); 13 | 14 | /// Gets a random int between [min] and [max]. 15 | static int getInt(int min, int max) { 16 | return min + random.nextInt(max - min); 17 | } 18 | 19 | /// Gets a random double between [min] and [max]. 20 | static double getDouble(double min, double max) { 21 | return min + random.nextDouble() * (max - min); 22 | } 23 | 24 | /// Gets a random boolean with chance [chance]. 25 | static bool getBool([double chance = 0.5]) { 26 | return random.nextDouble() < chance; 27 | } 28 | 29 | /// Randomize the positions of items in a list. 30 | static List shuffle(List list) { 31 | for (int i = 0, l = list.length; i < l; i++) { 32 | int j = random.nextInt(l); 33 | if (j == i) { 34 | continue; 35 | } 36 | dynamic item = list[j]; 37 | list[j] = list[i]; 38 | list[i] = item; 39 | } 40 | return list; 41 | } 42 | 43 | /// Randomly selects an item from a list. 44 | static dynamic getItem(List list) { 45 | return list[random.nextInt(list.length)]; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/03/clock_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'dart:ui'; 3 | 4 | import 'package:flutter/foundation.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/scheduler.dart'; 7 | 8 | import 'clock_fx.dart'; 9 | 10 | /// create by 张风捷特烈 on 2021/2/7 11 | /// contact me by email 1981462002@qq.com 12 | /// 说明: 13 | 14 | class ClockWidget extends StatefulWidget { 15 | final double radius; 16 | 17 | const ClockWidget({Key key, this.radius = 100}) : super(key: key); 18 | 19 | @override 20 | _ClockWidgetState createState() => _ClockWidgetState(); 21 | } 22 | 23 | class _ClockWidgetState extends State 24 | with SingleTickerProviderStateMixin { 25 | Ticker _ticker; 26 | ClockFx _fx; 27 | 28 | @override 29 | void initState() { 30 | super.initState(); 31 | _ticker = createTicker(_tick)..start(); 32 | _fx = ClockFx( 33 | size: Size(widget.radius * 2, widget.radius * 2), 34 | time: DateTime.now(), 35 | ); 36 | } 37 | 38 | @override 39 | void dispose() { 40 | _ticker.dispose(); 41 | _fx.dispose(); 42 | super.dispose(); 43 | } 44 | 45 | void _tick(Duration duration) { 46 | _fx.tick(duration); 47 | if (_fx.time.second != DateTime.now().second) { 48 | _fx.setTime(DateTime.now()); 49 | } 50 | } 51 | 52 | @override 53 | Widget build(BuildContext context) { 54 | return CustomPaint( 55 | size: Size(widget.radius * 2, widget.radius * 2), 56 | painter: ClockFxPainter(fx: _fx), 57 | ); 58 | } 59 | } 60 | 61 | /// Alpha value for noise particles. 62 | const double noiseAlpha = 160; 63 | 64 | class ClockFxPainter extends CustomPainter { 65 | final ClockFx fx; 66 | 67 | ClockFxPainter({@required this.fx}) : super(repaint: fx); 68 | 69 | @override 70 | void paint(Canvas canvas, Size size) { 71 | fx.particles.forEach((p) { 72 | double a; 73 | a = max(0.0, (p.distFrac - .13) / p.distFrac) * 255; 74 | a = min(a, min(noiseAlpha, p.lifeLeft * 3 * 255)); 75 | int alpha = a.floor(); 76 | 77 | Paint circlePaint = Paint() 78 | ..style = PaintingStyle.fill 79 | ..color = p.color.withAlpha(alpha); 80 | 81 | canvas.drawCircle(Offset(p.x, p.y), p.size, circlePaint); 82 | }); 83 | } 84 | 85 | @override 86 | bool shouldRepaint(covariant ClockFxPainter oldDelegate) => 87 | oldDelegate.fx != fx; 88 | } 89 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/03/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/03/particle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | class Particle { 7 | 8 | double x; // x 坐标 9 | double y; // y 坐标 10 | double vx; // x 速度 11 | double vy; // y 速度 12 | double a; // 发射弧度 13 | double dist; // 距离画布中心的长度 14 | double distFrac;// 距离画布中心的百分比 15 | double size;// 粒子大小 16 | double life; // 粒子寿命 17 | double lifeLeft; // 粒子剩余寿命 18 | bool isFilled; // 是否填充 19 | Color color; // 颜色 20 | int distribution; // 分配情况 21 | 22 | 23 | Particle({ 24 | this.x = 0, 25 | this.y = 0, 26 | this.a = 0, 27 | this.vx = 0, 28 | this.vy = 0, 29 | this.dist = 0, 30 | this.distFrac = 0, 31 | this.size = 0, 32 | this.life = 0, 33 | this.lifeLeft = 0, 34 | this.isFilled = false, 35 | this.color = Colors.blueAccent, 36 | this.distribution = 0, 37 | }); 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/03/utils/rnd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | 4 | class Rnd { 5 | static int _seed = DateTime.now().millisecondsSinceEpoch; 6 | static Random random = Random(_seed); 7 | 8 | static set seed(int val) => random = Random(_seed = val); 9 | static int get seed => _seed; 10 | 11 | /// Gets the next double. 12 | static get ratio => random.nextDouble(); 13 | 14 | /// Gets a random int between [min] and [max]. 15 | static int getInt(int min, int max) { 16 | return min + random.nextInt(max - min); 17 | } 18 | 19 | /// Gets a random double between [min] and [max]. 20 | static double getDouble(double min, double max) { 21 | return min + random.nextDouble() * (max - min); 22 | } 23 | 24 | /// Gets a random boolean with chance [chance]. 25 | static bool getBool([double chance = 0.5]) { 26 | return random.nextDouble() < chance; 27 | } 28 | 29 | /// Randomize the positions of items in a list. 30 | static List shuffle(List list) { 31 | for (int i = 0, l = list.length; i < l; i++) { 32 | int j = random.nextInt(l); 33 | if (j == i) { 34 | continue; 35 | } 36 | dynamic item = list[j]; 37 | list[j] = list[i]; 38 | list[i] = item; 39 | } 40 | return list; 41 | } 42 | 43 | /// Randomly selects an item from a list. 44 | static dynamic getItem(List list) { 45 | return list[random.nextInt(list.length)]; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/04/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | import 'clock_widget.dart'; 5 | 6 | 7 | void main() { 8 | WidgetsFlutterBinding.ensureInitialized(); // 确定初始化 9 | SystemChrome.setPreferredOrientations( // 使设备横屏显示 10 | [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]); 11 | SystemChrome.setEnabledSystemUIOverlays([]); // 全屏显示 12 | runApp(MyApp()); 13 | } 14 | 15 | class MyApp extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | debugShowCheckedModeBanner: false, 20 | title: 'Flutter Demo', 21 | theme: ThemeData( 22 | primarySwatch: Colors.blue, 23 | ), 24 | home: Scaffold( 25 | body: Center( 26 | child: ClockWidget(), 27 | )) 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/04/particle.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | 6 | class Particle { 7 | 8 | double x; // x 坐标 9 | double y; // y 坐标 10 | double vx; // x 速度 11 | double vy; // y 速度 12 | double a; // 发射弧度 13 | double dist; // 距离画布中心的长度 14 | double distFrac;// 距离画布中心的百分比 15 | double size;// 粒子大小 16 | double life; // 粒子寿命 17 | double lifeLeft; // 粒子剩余寿命 18 | bool isFilled; // 是否填充 19 | Color color; // 颜色 20 | int distribution; // 分配情况 21 | 22 | 23 | Particle({ 24 | this.x = 0, 25 | this.y = 0, 26 | this.a = 0, 27 | this.vx = 0, 28 | this.vy = 0, 29 | this.dist = 0, 30 | this.distFrac = 0, 31 | this.size = 0, 32 | this.life = 0, 33 | this.lifeLeft = 0, 34 | this.isFilled = false, 35 | this.color = Colors.blueAccent, 36 | this.distribution = 0, 37 | }); 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /lib/16_clock/06_lizi/04/utils/rnd.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | 4 | class Rnd { 5 | static int _seed = DateTime.now().millisecondsSinceEpoch; 6 | static Random random = Random(_seed); 7 | 8 | static set seed(int val) => random = Random(_seed = val); 9 | static int get seed => _seed; 10 | 11 | /// Gets the next double. 12 | static get ratio => random.nextDouble(); 13 | 14 | /// Gets a random int between [min] and [max]. 15 | static int getInt(int min, int max) { 16 | return min + random.nextInt(max - min); 17 | } 18 | 19 | /// Gets a random double between [min] and [max]. 20 | static double getDouble(double min, double max) { 21 | return min + random.nextDouble() * (max - min); 22 | } 23 | 24 | /// Gets a random boolean with chance [chance]. 25 | static bool getBool([double chance = 0.5]) { 26 | return random.nextDouble() < chance; 27 | } 28 | 29 | /// Randomize the positions of items in a list. 30 | static List shuffle(List list) { 31 | for (int i = 0, l = list.length; i < l; i++) { 32 | int j = random.nextInt(l); 33 | if (j == i) { 34 | continue; 35 | } 36 | dynamic item = list[j]; 37 | list[j] = list[i]; 38 | list[i] = item; 39 | } 40 | return list; 41 | } 42 | 43 | /// Randomly selects an item from a list. 44 | static dynamic getItem(List list) { 45 | return list[random.nextInt(list.length)]; 46 | } 47 | 48 | } 49 | --------------------------------------------------------------------------------