├── .gitignore
├── .idea
└── runConfigurations
│ └── main_dart.xml
├── .metadata
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── mono0926
│ │ │ │ └── animations
│ │ │ │ └── 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
├── apple_lock.flr
├── love.png
└── love_gray.png
├── deploy_web.sh
├── docs
├── .last_build_id
├── assets
│ ├── AssetManifest.json
│ ├── FontManifest.json
│ ├── NOTICES
│ ├── assets
│ │ ├── apple_lock.flr
│ │ ├── love.png
│ │ └── love_gray.png
│ ├── fonts
│ │ ├── MaterialIcons-Regular.otf
│ │ └── NothingYouCouldDo.ttf
│ └── packages
│ │ └── cupertino_icons
│ │ └── assets
│ │ └── CupertinoIcons.ttf
├── favicon.png
├── flutter_service_worker.js
├── icons
│ ├── Icon-192.png
│ └── Icon-512.png
├── index.html
├── main.dart.js
├── manifest.json
└── version.json
├── firebase
├── .firebaserc
├── .gitignore
└── firebase.json
├── fonts
└── NothingYouCouldDo.ttf
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── flutter_export_environment.sh
├── Podfile
├── 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
├── app.dart
├── main.dart
├── pages
│ ├── custom
│ │ ├── animated_builder_page.dart
│ │ ├── animated_switcher_page.dart
│ │ ├── animated_widget_page.dart
│ │ ├── animation_controller_set_state_enhanced2_page.dart
│ │ ├── animation_controller_set_state_enhanced_page.dart
│ │ ├── animation_controller_set_state_page.dart
│ │ ├── custom_page.dart
│ │ ├── implicitly_animated_widget_page.dart
│ │ ├── tween_animation_builder_page.dart
│ │ └── widget
│ │ │ ├── ghost_fade_tween.dart
│ │ │ └── switch_string_tween.dart
│ ├── flare
│ │ ├── apple_lock_page.dart
│ │ └── flare_page.dart
│ ├── flight_search
│ │ ├── README.md
│ │ ├── air_asia_bar.dart
│ │ ├── animated_dot.dart
│ │ ├── animated_plane_icon.dart
│ │ ├── content_card.dart
│ │ ├── fade_route.dart
│ │ ├── flight_search_page.dart
│ │ ├── flight_stop.dart
│ │ ├── flight_stop_card.dart
│ │ ├── flight_stop_ticker.dart
│ │ ├── multicity_input.dart
│ │ ├── price_tab.dart
│ │ ├── rounded_button.dart
│ │ ├── ticker_page.dart
│ │ └── ticket_card.dart
│ ├── home
│ │ └── home_page.dart
│ ├── implicitly_animated
│ │ ├── animated_align.dart
│ │ ├── animated_container.dart
│ │ ├── animated_cross_fade.dart
│ │ ├── animated_default_text_style.dart
│ │ ├── animated_icon.dart
│ │ ├── animated_list.dart
│ │ ├── animated_modal_barrier.dart
│ │ ├── animated_opacity.dart
│ │ ├── animated_padding.dart
│ │ ├── animated_physical_model.dart
│ │ ├── animated_positioned.dart
│ │ ├── animated_positioned_directional.dart
│ │ ├── animated_size_page.dart
│ │ ├── animated_switcher_page.dart
│ │ ├── animated_theme_page.dart
│ │ ├── fade_in_image_page.dart
│ │ ├── hero_page.dart
│ │ └── implicitly_animated_page.dart
│ └── transition
│ │ ├── align_transition_page.dart
│ │ ├── decorated_box_transition_page.dart
│ │ ├── default_text_style_transition_page.dart
│ │ ├── fade_transition_page.dart
│ │ ├── positioned_transition_page.dart
│ │ ├── relative_positioned_transition_page.dart
│ │ ├── rotation_transition_page.dart
│ │ ├── scale_transition_page.dart
│ │ ├── size_transition_page.dart
│ │ ├── slide_transition_page.dart
│ │ └── transition_page.dart
├── util
│ ├── logger.dart
│ └── util.dart
└── widget
│ ├── animation_object.dart
│ ├── app_list_tile.dart
│ ├── app_scaffold.dart
│ └── widget.dart
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Podfile.lock
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── app_icon_1024.png
│ │ ├── app_icon_128.png
│ │ ├── app_icon_16.png
│ │ ├── app_icon_256.png
│ │ ├── app_icon_32.png
│ │ ├── app_icon_512.png
│ │ └── app_icon_64.png
│ ├── Base.lproj
│ └── MainMenu.xib
│ ├── Configs
│ ├── AppInfo.xcconfig
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
├── pubspec.lock
├── pubspec.yaml
├── res
└── values
│ └── strings_en.arb
├── test
└── widget_test.dart
└── web
├── favicon.png
├── icons
├── Icon-192.png
└── Icon-512.png
├── index.html
└── manifest.json
/.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 | !.idea/runConfigurations/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | **/doc/api/
26 | **/ios/Flutter/.last_build_id
27 | .dart_tool/
28 | .flutter-plugins
29 | .flutter-plugins-dependencies
30 | .packages
31 | .pub-cache/
32 | .pub/
33 | /build/
34 |
35 | # Web related
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Exceptions to above rules.
44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
45 |
46 | vendor/
47 |
48 | **/fastlane/report.xml
49 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/main_dart.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
8 | channel: beta
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Masayuki Ono
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Animation Example
2 |
3 | - [x] Implicitly Animated Widgets (Inherited form [ImplicitlyAnimatedWidget](https://docs.flutter.io/flutter/widgets/ImplicitlyAnimatedWidget-class.html))
4 | - [x] Transition Widgets
5 | - [x] Explicit Widgets
6 | - [AnimatedWidget](https://docs.flutter.io/flutter/widgets/AnimatedWidget-class.html)
7 | - [AnimatedBuilder](https://docs.flutter.io/flutter/widgets/AnimatedBuilder-class.html)
8 | - [ImplicitlyAnimatedWidget](https://docs.flutter.io/flutter/widgets/ImplicitlyAnimatedWidget-class.html)
9 |
10 |
11 | ## Articles
12 |
13 | - [Flutter のお手軽にアニメーションを扱える Animated 系 Widget をすべて紹介](https://medium.com/flutter-jp/implicit-animation-b9d4b7358c28)
14 | - [FlutterのTransition系アニメーションWidgetをすべて紹介](https://medium.com/flutter-jp/implicit-animation-b9d4b7358c28)
15 | - [“The Boring Flutter Development Show” で取り上げられたアニメーションを様々な方法で書きながら解説](https://medium.com/flutter-jp/custom-animation-c87e9d55b03b)
16 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # https://pub.dev/packages/pedantic_mono
2 | include: package:pedantic_mono/analysis_options.yaml
3 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/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 | compileOptions {
32 | sourceCompatibility JavaVersion.VERSION_1_8
33 | targetCompatibility JavaVersion.VERSION_1_8
34 | }
35 |
36 | kotlinOptions {
37 | jvmTarget = '1.8'
38 | }
39 |
40 | sourceSets {
41 | main.java.srcDirs += 'src/main/kotlin'
42 | }
43 |
44 | defaultConfig {
45 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
46 | applicationId "com.mono0926.animations"
47 | minSdkVersion 16
48 | targetSdkVersion 30
49 | versionCode flutterVersionCode.toInteger()
50 | versionName flutterVersionName
51 | }
52 |
53 | buildTypes {
54 | release {
55 | // TODO: Add your own signing config for the release build.
56 | // Signing with the debug keys for now, so `flutter run --release` works.
57 | signingConfig signingConfigs.debug
58 | }
59 | }
60 | }
61 |
62 | flutter {
63 | source '../..'
64 | }
65 |
66 | dependencies {
67 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
68 | }
69 |
--------------------------------------------------------------------------------
/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/mono0926/animations/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.mono0926.animations
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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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 | mavenCentral()
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 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/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/apple_lock.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/assets/apple_lock.flr
--------------------------------------------------------------------------------
/assets/love.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/assets/love.png
--------------------------------------------------------------------------------
/assets/love_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/assets/love_gray.png
--------------------------------------------------------------------------------
/deploy_web.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zsh
2 |
3 | flutter build web
4 | rm -rf firebase/public/animation
5 | mv build/web firebase/public/animation
6 | cd firebase
7 | firebase deploy --only hosting:animation
8 |
--------------------------------------------------------------------------------
/docs/.last_build_id:
--------------------------------------------------------------------------------
1 | 75db79b7f0256732a78385f710902af9
--------------------------------------------------------------------------------
/docs/assets/AssetManifest.json:
--------------------------------------------------------------------------------
1 | {"assets/apple_lock.flr":["assets/apple_lock.flr"],"assets/love.png":["assets/love.png"],"assets/love_gray.png":["assets/love_gray.png"],"fonts/NothingYouCouldDo.ttf":["fonts/NothingYouCouldDo.ttf"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}
--------------------------------------------------------------------------------
/docs/assets/FontManifest.json:
--------------------------------------------------------------------------------
1 | [{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"NothingYouCouldDo","fonts":[{"asset":"fonts/NothingYouCouldDo.ttf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]
--------------------------------------------------------------------------------
/docs/assets/assets/apple_lock.flr:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/assets/apple_lock.flr
--------------------------------------------------------------------------------
/docs/assets/assets/love.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/assets/love.png
--------------------------------------------------------------------------------
/docs/assets/assets/love_gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/assets/love_gray.png
--------------------------------------------------------------------------------
/docs/assets/fonts/MaterialIcons-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/fonts/MaterialIcons-Regular.otf
--------------------------------------------------------------------------------
/docs/assets/fonts/NothingYouCouldDo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/fonts/NothingYouCouldDo.ttf
--------------------------------------------------------------------------------
/docs/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/assets/packages/cupertino_icons/assets/CupertinoIcons.ttf
--------------------------------------------------------------------------------
/docs/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/favicon.png
--------------------------------------------------------------------------------
/docs/flutter_service_worker.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | const MANIFEST = 'flutter-app-manifest';
3 | const TEMP = 'flutter-temp-cache';
4 | const CACHE_NAME = 'flutter-app-cache';
5 | const RESOURCES = {
6 | "version.json": "f2a7be411659caece6901acd54b706d3",
7 | "index.html": "d0c2e544c50aa7bf00f70e7c0783c154",
8 | "/": "d0c2e544c50aa7bf00f70e7c0783c154",
9 | "main.dart.js": "6dcbeb6a3d567e4969c058cd5cf856d6",
10 | "favicon.png": "5dcef449791fa27946b3d35ad8803796",
11 | "icons/Icon-192.png": "ac9a721a12bbc803b44f645561ecb1e1",
12 | "icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1",
13 | "manifest.json": "785b06c3e8c6ba5d4c04ee9ac2a3ae5e",
14 | "assets/AssetManifest.json": "3391632d06375c0d794dee6cafc6c232",
15 | "assets/NOTICES": "7f9e46a2c4e7e8759f2ffc96fb7a102b",
16 | "assets/FontManifest.json": "a4df2cc5008d99c0be44f6c46cecf41c",
17 | "assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "6d342eb68f170c97609e9da345464e5e",
18 | "assets/fonts/NothingYouCouldDo.ttf": "928b116194fd8f799c4b8c58ce8aa734",
19 | "assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
20 | "assets/assets/love_gray.png": "2781e2665297e3b208cdd340cb836398",
21 | "assets/assets/apple_lock.flr": "a8d0626cbab91ac731f3d2551c138357",
22 | "assets/assets/love.png": "3091c01fc119a68bd7f1d20f9e1e92d8"
23 | };
24 |
25 | // The application shell files that are downloaded before a service worker can
26 | // start.
27 | const CORE = [
28 | "/",
29 | "main.dart.js",
30 | "index.html",
31 | "assets/NOTICES",
32 | "assets/AssetManifest.json",
33 | "assets/FontManifest.json"];
34 | // During install, the TEMP cache is populated with the application shell files.
35 | self.addEventListener("install", (event) => {
36 | self.skipWaiting();
37 | return event.waitUntil(
38 | caches.open(TEMP).then((cache) => {
39 | return cache.addAll(
40 | CORE.map((value) => new Request(value, {'cache': 'reload'})));
41 | })
42 | );
43 | });
44 |
45 | // During activate, the cache is populated with the temp files downloaded in
46 | // install. If this service worker is upgrading from one with a saved
47 | // MANIFEST, then use this to retain unchanged resource files.
48 | self.addEventListener("activate", function(event) {
49 | return event.waitUntil(async function() {
50 | try {
51 | var contentCache = await caches.open(CACHE_NAME);
52 | var tempCache = await caches.open(TEMP);
53 | var manifestCache = await caches.open(MANIFEST);
54 | var manifest = await manifestCache.match('manifest');
55 | // When there is no prior manifest, clear the entire cache.
56 | if (!manifest) {
57 | await caches.delete(CACHE_NAME);
58 | contentCache = await caches.open(CACHE_NAME);
59 | for (var request of await tempCache.keys()) {
60 | var response = await tempCache.match(request);
61 | await contentCache.put(request, response);
62 | }
63 | await caches.delete(TEMP);
64 | // Save the manifest to make future upgrades efficient.
65 | await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
66 | return;
67 | }
68 | var oldManifest = await manifest.json();
69 | var origin = self.location.origin;
70 | for (var request of await contentCache.keys()) {
71 | var key = request.url.substring(origin.length + 1);
72 | if (key == "") {
73 | key = "/";
74 | }
75 | // If a resource from the old manifest is not in the new cache, or if
76 | // the MD5 sum has changed, delete it. Otherwise the resource is left
77 | // in the cache and can be reused by the new service worker.
78 | if (!RESOURCES[key] || RESOURCES[key] != oldManifest[key]) {
79 | await contentCache.delete(request);
80 | }
81 | }
82 | // Populate the cache with the app shell TEMP files, potentially overwriting
83 | // cache files preserved above.
84 | for (var request of await tempCache.keys()) {
85 | var response = await tempCache.match(request);
86 | await contentCache.put(request, response);
87 | }
88 | await caches.delete(TEMP);
89 | // Save the manifest to make future upgrades efficient.
90 | await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
91 | return;
92 | } catch (err) {
93 | // On an unhandled exception the state of the cache cannot be guaranteed.
94 | console.error('Failed to upgrade service worker: ' + err);
95 | await caches.delete(CACHE_NAME);
96 | await caches.delete(TEMP);
97 | await caches.delete(MANIFEST);
98 | }
99 | }());
100 | });
101 |
102 | // The fetch handler redirects requests for RESOURCE files to the service
103 | // worker cache.
104 | self.addEventListener("fetch", (event) => {
105 | if (event.request.method !== 'GET') {
106 | return;
107 | }
108 | var origin = self.location.origin;
109 | var key = event.request.url.substring(origin.length + 1);
110 | // Redirect URLs to the index.html
111 | if (key.indexOf('?v=') != -1) {
112 | key = key.split('?v=')[0];
113 | }
114 | if (event.request.url == origin || event.request.url.startsWith(origin + '/#') || key == '') {
115 | key = '/';
116 | }
117 | // If the URL is not the RESOURCE list then return to signal that the
118 | // browser should take over.
119 | if (!RESOURCES[key]) {
120 | return;
121 | }
122 | // If the URL is the index.html, perform an online-first request.
123 | if (key == '/') {
124 | return onlineFirst(event);
125 | }
126 | event.respondWith(caches.open(CACHE_NAME)
127 | .then((cache) => {
128 | return cache.match(event.request).then((response) => {
129 | // Either respond with the cached resource, or perform a fetch and
130 | // lazily populate the cache.
131 | return response || fetch(event.request).then((response) => {
132 | cache.put(event.request, response.clone());
133 | return response;
134 | });
135 | })
136 | })
137 | );
138 | });
139 |
140 | self.addEventListener('message', (event) => {
141 | // SkipWaiting can be used to immediately activate a waiting service worker.
142 | // This will also require a page refresh triggered by the main worker.
143 | if (event.data === 'skipWaiting') {
144 | self.skipWaiting();
145 | return;
146 | }
147 | if (event.data === 'downloadOffline') {
148 | downloadOffline();
149 | return;
150 | }
151 | });
152 |
153 | // Download offline will check the RESOURCES for all files not in the cache
154 | // and populate them.
155 | async function downloadOffline() {
156 | var resources = [];
157 | var contentCache = await caches.open(CACHE_NAME);
158 | var currentContent = {};
159 | for (var request of await contentCache.keys()) {
160 | var key = request.url.substring(origin.length + 1);
161 | if (key == "") {
162 | key = "/";
163 | }
164 | currentContent[key] = true;
165 | }
166 | for (var resourceKey of Object.keys(RESOURCES)) {
167 | if (!currentContent[resourceKey]) {
168 | resources.push(resourceKey);
169 | }
170 | }
171 | return contentCache.addAll(resources);
172 | }
173 |
174 | // Attempt to download the resource online before falling back to
175 | // the offline cache.
176 | function onlineFirst(event) {
177 | return event.respondWith(
178 | fetch(event.request).then((response) => {
179 | return caches.open(CACHE_NAME).then((cache) => {
180 | cache.put(event.request, response.clone());
181 | return response;
182 | });
183 | }).catch((error) => {
184 | return caches.open(CACHE_NAME).then((cache) => {
185 | return cache.match(event.request).then((response) => {
186 | if (response != null) {
187 | return response;
188 | }
189 | throw error;
190 | });
191 | });
192 | })
193 | );
194 | }
195 |
--------------------------------------------------------------------------------
/docs/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/icons/Icon-192.png
--------------------------------------------------------------------------------
/docs/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/docs/icons/Icon-512.png
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | animations
27 |
28 |
29 |
30 |
33 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/docs/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "animations",
3 | "short_name": "animations",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/docs/version.json:
--------------------------------------------------------------------------------
1 | {"app_name":"animations_app","version":"1.1.0","build_number":null}
--------------------------------------------------------------------------------
/firebase/.firebaserc:
--------------------------------------------------------------------------------
1 | {
2 | "projects": {
3 | "default": "mono-firebase"
4 | },
5 | "targets": {
6 | "mono-firebase": {
7 | "hosting": {
8 | "animation": [
9 | "animation-mono"
10 | ]
11 | }
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/firebase/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | firebase-debug.log*
8 | firebase-debug.*.log*
9 |
10 | # Firebase cache
11 | .firebase/
12 |
13 | # Firebase config
14 |
15 | # Uncomment this if you'd like others to create their own Firebase project.
16 | # For a team working on the same Firebase project(s), it is recommended to leave
17 | # it commented so all members can deploy to the same project(s) in .firebaserc.
18 | # .firebaserc
19 |
20 | # Runtime data
21 | pids
22 | *.pid
23 | *.seed
24 | *.pid.lock
25 |
26 | # Directory for instrumented libs generated by jscoverage/JSCover
27 | lib-cov
28 |
29 | # Coverage directory used by tools like istanbul
30 | coverage
31 |
32 | # nyc test coverage
33 | .nyc_output
34 |
35 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
36 | .grunt
37 |
38 | # Bower dependency directory (https://bower.io/)
39 | bower_components
40 |
41 | # node-waf configuration
42 | .lock-wscript
43 |
44 | # Compiled binary addons (http://nodejs.org/api/addons.html)
45 | build/Release
46 |
47 | # Dependency directories
48 | node_modules/
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Optional REPL history
57 | .node_repl_history
58 |
59 | # Output of 'npm pack'
60 | *.tgz
61 |
62 | # Yarn Integrity file
63 | .yarn-integrity
64 |
65 | # dotenv environment variables file
66 | .env
67 |
68 | public/
69 |
--------------------------------------------------------------------------------
/firebase/firebase.json:
--------------------------------------------------------------------------------
1 | {
2 | "hosting": [
3 | {
4 | "target": "animation",
5 | "public": "public/animation",
6 | "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
7 | "rewrites": [
8 | {
9 | "source": "**",
10 | "destination": "/index.html"
11 | }
12 | ]
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/fonts/NothingYouCouldDo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/fonts/NothingYouCouldDo.ttf
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/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 "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=/Users/mono/fvm/versions/beta"
4 | export "FLUTTER_APPLICATION_PATH=/Users/mono/Git/flutter-animations"
5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true"
6 | export "FLUTTER_TARGET=lib/main.dart"
7 | export "FLUTTER_BUILD_DIR=build"
8 | export "FLUTTER_BUILD_NAME=1.1.0"
9 | export "FLUTTER_BUILD_NUMBER=1.1.0"
10 | export "DART_OBFUSCATION=false"
11 | export "TRACK_WIDGET_CREATION=true"
12 | export "TREE_SHAKE_ICONS=false"
13 | export "PACKAGE_CONFIG=.dart_tool/package_config.json"
14 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def parse_KV_file(file, separator='=')
14 | file_abs_path = File.expand_path(file)
15 | if !File.exists? file_abs_path
16 | return [];
17 | end
18 | pods_ary = []
19 | skip_line_start_symbols = ["#", "/"]
20 | File.foreach(file_abs_path) { |line|
21 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
22 | plugin = line.split(pattern=separator)
23 | if plugin.length == 2
24 | podname = plugin[0].strip()
25 | path = plugin[1].strip()
26 | podpath = File.expand_path("#{path}", file_abs_path)
27 | pods_ary.push({:name => podname, :path => podpath});
28 | else
29 | puts "Invalid plugin specification: #{line}"
30 | end
31 | }
32 | return pods_ary
33 | end
34 |
35 | target 'Runner' do
36 | use_frameworks!
37 |
38 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
39 | # referring to absolute paths on developers' machines.
40 | system('rm -rf .symlinks')
41 | system('mkdir -p .symlinks/plugins')
42 |
43 | # Flutter Pods
44 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
45 | if generated_xcode_build_settings.empty?
46 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
47 | end
48 | generated_xcode_build_settings.map { |p|
49 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
50 | symlink = File.join('.symlinks', 'flutter')
51 | File.symlink(File.dirname(p[:path]), symlink)
52 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
53 | end
54 | }
55 |
56 | # Plugin Pods
57 | plugin_pods = parse_KV_file('../.flutter-plugins')
58 | plugin_pods.map { |p|
59 | symlink = File.join('.symlinks', 'plugins', p[:name])
60 | File.symlink(p[:path], symlink)
61 | pod p[:name], :path => File.join(symlink, 'ios')
62 | }
63 | end
64 |
65 | post_install do |installer|
66 | installer.pods_project.targets.each do |target|
67 | target.build_configurations.each do |config|
68 | config.build_settings['ENABLE_BITCODE'] = 'NO'
69 | end
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/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.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/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 | BuildSystemType
6 | Original
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: [UIApplicationLaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/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 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | animations
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"
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/app.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // TODO(mono): ナビゲーションバー右にソース見られるボタンを置きたい(他のアプリを参考にする)
5 | void main() => runApp(const App());
6 |
--------------------------------------------------------------------------------
/lib/pages/custom/animated_builder_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/widget/ghost_fade_tween.dart';
2 | import 'package:animations_app/pages/custom/widget/switch_string_tween.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimatedBuilderPage extends StatefulWidget {
7 | const AnimatedBuilderPage({super.key});
8 |
9 | static const routeName = 'AnimatedBuilderPage';
10 |
11 | @override
12 | State createState() => _AnimatedBuilderPageState();
13 | }
14 |
15 | class _AnimatedBuilderPageState extends State
16 | with SingleTickerProviderStateMixin {
17 | static const _texts = [
18 | 'First',
19 | 'Second',
20 | 'Third',
21 | ];
22 | static const _colors = [
23 | Colors.black,
24 | Colors.blue,
25 | Colors.red,
26 | ];
27 | var _index = 0;
28 | String get _currentText => _texts[_index % 3];
29 | Color get _currentColor => _colors[_index % 3];
30 |
31 | late final AnimationController _animation = AnimationController(
32 | vsync: this,
33 | duration: const Duration(milliseconds: 1000),
34 | );
35 | late GhostFadeTween _colorTween = GhostFadeTween(
36 | begin: _currentColor,
37 | end: _currentColor,
38 | );
39 | late SwitchStringTween _stringTween = SwitchStringTween(
40 | begin: _currentText,
41 | end: _currentText,
42 | );
43 |
44 | @override
45 | void dispose() {
46 | _animation.dispose();
47 | super.dispose();
48 | }
49 |
50 | @override
51 | Widget build(BuildContext context) {
52 | return AppScaffold(
53 | title: 'AnimatedBuilder',
54 | floatingActionButton: FloatingActionButton(
55 | onPressed: () {
56 | setState(() {
57 | _index++;
58 | _colorTween = GhostFadeTween(
59 | begin: _colorTween.end,
60 | end: _currentColor,
61 | );
62 | _stringTween = SwitchStringTween(
63 | begin: _stringTween.end,
64 | end: _currentText,
65 | );
66 | });
67 | _animation.forward(from: 0);
68 | },
69 | child: const Icon(Icons.refresh),
70 | ),
71 | child: Center(
72 | child: AnimatedBuilder(
73 | animation: _animation,
74 | builder: (context, child) {
75 | // 一般的にchildは利用するべきだが今回は不要
76 | return Text(
77 | _stringTween.evaluate(_animation),
78 | style: Theme.of(context)
79 | .textTheme
80 | .headline6!
81 | .copyWith(color: _colorTween.evaluate(_animation)),
82 | );
83 | },
84 | ),
85 | ),
86 | );
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/lib/pages/custom/animated_switcher_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedSwitcher2Page extends StatefulWidget {
5 | const AnimatedSwitcher2Page({super.key});
6 |
7 | static const routeName = 'AnimatedSwitcher2Page';
8 |
9 | @override
10 | State createState() => _AnimatedSwitcher2PageState();
11 | }
12 |
13 | class _AnimatedSwitcher2PageState extends State {
14 | static const _texts = [
15 | 'First',
16 | 'Second',
17 | 'Third',
18 | ];
19 | static const _colors = [
20 | Colors.black,
21 | Colors.blue,
22 | Colors.red,
23 | ];
24 | var _index = 0;
25 | String get _currentText => _texts[_index % 3];
26 | Color get _currentColor => _colors[_index % 3];
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return AppScaffold(
31 | title: 'AnimatedSwitcher',
32 | floatingActionButton: FloatingActionButton(
33 | onPressed: () {
34 | setState(() {
35 | _index++;
36 | });
37 | },
38 | child: const Icon(Icons.refresh),
39 | ),
40 | child: Center(
41 | child: AnimatedSwitcher(
42 | duration: const Duration(milliseconds: 1000),
43 | transitionBuilder: (child, animation) {
44 | return FadeTransition(
45 | opacity:
46 | animation.drive(CurveTween(curve: const Interval(0.5, 1))),
47 | child: child,
48 | );
49 | },
50 | child: Text(
51 | _currentText,
52 | key: ValueKey(_currentText),
53 | style: Theme.of(context)
54 | .textTheme
55 | .headline6!
56 | .copyWith(color: _currentColor),
57 | ),
58 | ),
59 | ),
60 | );
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/lib/pages/custom/animated_widget_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/widget/ghost_fade_tween.dart';
2 | import 'package:animations_app/pages/custom/widget/switch_string_tween.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimatedWidgetPage extends StatefulWidget {
7 | const AnimatedWidgetPage({super.key});
8 |
9 | static const routeName = 'AnimatedWidgetPage';
10 |
11 | @override
12 | State createState() => _AnimatedWidgetPageState();
13 | }
14 |
15 | class _AnimatedWidgetPageState extends State
16 | with SingleTickerProviderStateMixin {
17 | static const _texts = [
18 | 'First',
19 | 'Second',
20 | 'Third',
21 | ];
22 | static const _colors = [
23 | Colors.black,
24 | Colors.blue,
25 | Colors.red,
26 | ];
27 | var _index = 0;
28 | String get _currentText => _texts[_index % 3];
29 | Color get _currentColor => _colors[_index % 3];
30 |
31 | late final AnimationController _animation = AnimationController(
32 | vsync: this,
33 | duration: const Duration(milliseconds: 1000),
34 | );
35 | late GhostFadeTween _colorTween = GhostFadeTween(
36 | begin: _currentColor,
37 | end: _currentColor,
38 | );
39 | late SwitchStringTween _stringTween = SwitchStringTween(
40 | begin: _currentText,
41 | end: _currentText,
42 | );
43 |
44 | @override
45 | void dispose() {
46 | _animation.dispose();
47 | super.dispose();
48 | }
49 |
50 | @override
51 | Widget build(BuildContext context) {
52 | return AppScaffold(
53 | title: 'AnimatedWidget',
54 | floatingActionButton: FloatingActionButton(
55 | onPressed: () {
56 | setState(() {
57 | _index++;
58 | _colorTween = GhostFadeTween(
59 | begin: _colorTween.end,
60 | end: _currentColor,
61 | );
62 | _stringTween = SwitchStringTween(
63 | begin: _stringTween.end,
64 | end: _currentText,
65 | );
66 | });
67 | _animation.forward(from: 0);
68 | },
69 | child: const Icon(Icons.refresh),
70 | ),
71 | child: Center(
72 | child: _TextStyleColorTransition(
73 | animation: _animation.drive(_colorTween),
74 | style: Theme.of(context).textTheme.headline6!,
75 | child: _StringTransition(animation: _animation.drive(_stringTween)),
76 | ),
77 | ),
78 | );
79 | }
80 | }
81 |
82 | class _TextStyleColorTransition extends AnimatedWidget {
83 | const _TextStyleColorTransition({
84 | required this.child,
85 | required this.style,
86 | required Animation animation,
87 | }) : super(
88 | listenable: animation,
89 | );
90 |
91 | final Widget child;
92 | final TextStyle style;
93 |
94 | @override
95 | Widget build(BuildContext context) {
96 | final animation = listenable as Animation;
97 | return DefaultTextStyle(
98 | style: style.copyWith(color: animation.value),
99 | child: child,
100 | );
101 | }
102 | }
103 |
104 | class _StringTransition extends AnimatedWidget {
105 | const _StringTransition({
106 | required Animation animation,
107 | }) : super(
108 | listenable: animation,
109 | );
110 |
111 | @override
112 | Widget build(BuildContext context) {
113 | final animation = listenable as Animation;
114 | return Text(animation.value);
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/lib/pages/custom/animation_controller_set_state_enhanced2_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/widget/ghost_fade_tween.dart';
2 | import 'package:animations_app/pages/custom/widget/switch_string_tween.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimationControllerSetStateEnhanced2Page extends StatefulWidget {
7 | const AnimationControllerSetStateEnhanced2Page({super.key});
8 |
9 | static const routeName = 'AnimationControllerSetStateEnhanced2';
10 |
11 | @override
12 | State createState() =>
13 | _AnimationControllerSetStateEnhanced2PageState();
14 | }
15 |
16 | class _AnimationControllerSetStateEnhanced2PageState
17 | extends State
18 | with SingleTickerProviderStateMixin {
19 | static const _texts = [
20 | 'First',
21 | 'Second',
22 | 'Third',
23 | ];
24 | static const _colors = [
25 | Colors.black,
26 | Colors.blue,
27 | Colors.red,
28 | ];
29 | var _index = 0;
30 | String get _currentText => _texts[_index % 3];
31 | Color get _currentColor => _colors[_index % 3];
32 |
33 | late GhostFadeTween _colorTween = GhostFadeTween(
34 | begin: _currentColor,
35 | end: _currentColor,
36 | );
37 | late SwitchStringTween _stringTween = SwitchStringTween(
38 | begin: _currentText,
39 | end: _currentText,
40 | );
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | return AppScaffold(
45 | title: 'AnimationController - SetState (Enhanced)',
46 | floatingActionButton: FloatingActionButton(
47 | onPressed: () {
48 | setState(() {
49 | _index++;
50 | _colorTween = GhostFadeTween(
51 | begin: _colorTween.end,
52 | end: _currentColor,
53 | );
54 | _stringTween = SwitchStringTween(
55 | begin: _stringTween.end,
56 | end: _currentText,
57 | );
58 | });
59 | },
60 | child: const Icon(Icons.refresh),
61 | ),
62 | child: Center(
63 | child: _MyAnimatedWidget(
64 | stringTween: _stringTween,
65 | colorTween: _colorTween,
66 | ),
67 | ),
68 | );
69 | }
70 | }
71 |
72 | class _MyAnimatedWidget extends StatefulWidget {
73 | const _MyAnimatedWidget({
74 | required this.stringTween,
75 | required this.colorTween,
76 | });
77 |
78 | final SwitchStringTween stringTween;
79 | final GhostFadeTween colorTween;
80 |
81 | @override
82 | State<_MyAnimatedWidget> createState() => __MyAnimatedWidgetState();
83 | }
84 |
85 | class __MyAnimatedWidgetState extends State<_MyAnimatedWidget>
86 | with SingleTickerProviderStateMixin {
87 | late final AnimationController _animation = AnimationController(
88 | vsync: this,
89 | duration: const Duration(milliseconds: 1000),
90 | )..addListener(() {
91 | setState(() {});
92 | });
93 |
94 | @override
95 | void dispose() {
96 | _animation.dispose();
97 | super.dispose();
98 | }
99 |
100 | @override
101 | void didUpdateWidget(_MyAnimatedWidget oldWidget) {
102 | super.didUpdateWidget(oldWidget);
103 | if (oldWidget.colorTween != widget.colorTween &&
104 | oldWidget.stringTween != widget.stringTween) {
105 | _animation.forward(from: 0);
106 | }
107 | }
108 |
109 | @override
110 | Widget build(BuildContext context) {
111 | return Text(
112 | widget.stringTween.evaluate(_animation),
113 | style: Theme.of(context).textTheme.headline6!.copyWith(
114 | color: widget.colorTween.evaluate(_animation),
115 | ),
116 | );
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/lib/pages/custom/animation_controller_set_state_enhanced_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/widget/ghost_fade_tween.dart';
2 | import 'package:animations_app/pages/custom/widget/switch_string_tween.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimationControllerSetStateEnhancedPage extends StatefulWidget {
7 | const AnimationControllerSetStateEnhancedPage({super.key});
8 |
9 | static const routeName = 'AnimationControllerSetStateEnhanced';
10 |
11 | @override
12 | State createState() =>
13 | _AnimationControllerSetStateEnhancedPageState();
14 | }
15 |
16 | class _AnimationControllerSetStateEnhancedPageState
17 | extends State
18 | with SingleTickerProviderStateMixin {
19 | static const _texts = [
20 | 'First',
21 | 'Second',
22 | 'Third',
23 | ];
24 | static const _colors = [
25 | Colors.black,
26 | Colors.blue,
27 | Colors.red,
28 | ];
29 | var _index = 0;
30 | String get _currentText => _texts[_index % 3];
31 | Color get _currentColor => _colors[_index % 3];
32 |
33 | late final AnimationController _animation = AnimationController(
34 | vsync: this,
35 | duration: const Duration(milliseconds: 1000),
36 | )..addListener(() {
37 | setState(() {});
38 | });
39 | late GhostFadeTween _colorTween = GhostFadeTween(
40 | begin: _currentColor,
41 | end: _currentColor,
42 | );
43 | late SwitchStringTween _stringTween = SwitchStringTween(
44 | begin: _currentText,
45 | end: _currentText,
46 | );
47 |
48 | @override
49 | void dispose() {
50 | _animation.dispose();
51 | super.dispose();
52 | }
53 |
54 | @override
55 | Widget build(BuildContext context) {
56 | return AppScaffold(
57 | title: 'AnimationController - SetState (Enhanced)',
58 | floatingActionButton: FloatingActionButton(
59 | onPressed: () {
60 | setState(() {
61 | _index++;
62 | _colorTween = GhostFadeTween(
63 | begin: _colorTween.end,
64 | end: _currentColor,
65 | );
66 | _stringTween = SwitchStringTween(
67 | begin: _stringTween.end,
68 | end: _currentText,
69 | );
70 | });
71 | _animation.forward(from: 0);
72 | },
73 | child: const Icon(Icons.refresh),
74 | ),
75 | child: Center(
76 | child: Text(
77 | _stringTween.evaluate(_animation),
78 | style: Theme.of(context).textTheme.headline6!.copyWith(
79 | color: _colorTween.evaluate(_animation),
80 | ),
81 | ),
82 | ),
83 | );
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/pages/custom/animation_controller_set_state_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimationControllerSetStatePage extends StatefulWidget {
5 | const AnimationControllerSetStatePage({super.key});
6 |
7 | static const routeName = 'AnimationControllerSetState';
8 |
9 | @override
10 | State createState() =>
11 | _AnimationControllerSetStatePageState();
12 | }
13 |
14 | class _AnimationControllerSetStatePageState
15 | extends State
16 | with SingleTickerProviderStateMixin {
17 | static const _texts = [
18 | 'First',
19 | 'Second',
20 | 'Third',
21 | ];
22 | static const _colors = [
23 | Colors.black,
24 | Colors.blue,
25 | Colors.red,
26 | ];
27 | var _index = 0;
28 | String get _currentText => _texts[_index % 3];
29 | Color get _currentColor => _colors[_index % 3];
30 |
31 | late final AnimationController _animation = AnimationController(
32 | vsync: this,
33 | duration: const Duration(milliseconds: 1000),
34 | )..addListener(() {
35 | setState(() {});
36 | });
37 | late ColorTween _colorTween = ColorTween(
38 | begin: _currentColor,
39 | end: _currentColor,
40 | );
41 |
42 | @override
43 | void dispose() {
44 | _animation.dispose();
45 | super.dispose();
46 | }
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | return AppScaffold(
51 | title: 'AnimationController - SetState',
52 | floatingActionButton: FloatingActionButton(
53 | onPressed: () {
54 | setState(() {
55 | _index++;
56 | _colorTween = ColorTween(
57 | begin: _colorTween.end,
58 | end: _currentColor,
59 | );
60 | });
61 | _animation.forward(from: 0);
62 | },
63 | child: const Icon(Icons.refresh),
64 | ),
65 | child: Center(
66 | child: Text(
67 | _currentText,
68 | style: Theme.of(context).textTheme.headline6!.copyWith(
69 | color: _colorTween.evaluate(_animation),
70 | ),
71 | ),
72 | ),
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/pages/custom/custom_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/animated_builder_page.dart';
2 | import 'package:animations_app/pages/custom/animated_switcher_page.dart';
3 | import 'package:animations_app/pages/custom/animated_widget_page.dart';
4 | import 'package:animations_app/pages/custom/animation_controller_set_state_enhanced2_page.dart';
5 | import 'package:animations_app/pages/custom/animation_controller_set_state_enhanced_page.dart';
6 | import 'package:animations_app/pages/custom/animation_controller_set_state_page.dart';
7 | import 'package:animations_app/pages/custom/implicitly_animated_widget_page.dart';
8 | import 'package:animations_app/widget/app_list_tile.dart';
9 | import 'package:animations_app/widget/app_scaffold.dart';
10 | import 'package:flutter/material.dart';
11 |
12 | import 'tween_animation_builder_page.dart';
13 |
14 | class CustomPage extends StatelessWidget {
15 | const CustomPage({super.key});
16 |
17 | static const routeName = 'Custom';
18 | @override
19 | Widget build(BuildContext context) {
20 | return AppScaffold(
21 | title: 'Custom',
22 | child: ListView(
23 | children: const [
24 | AppListTile(
25 | title: 'AnimationController - SetState',
26 | nextRouteName: AnimationControllerSetStatePage.routeName,
27 | ),
28 | AppListTile(
29 | title: 'AnimationController - SetState (Enhanced)',
30 | nextRouteName: AnimationControllerSetStateEnhancedPage.routeName,
31 | ),
32 | AppListTile(
33 | title: 'AnimationController - SetState (Enhanced2)',
34 | nextRouteName: AnimationControllerSetStateEnhanced2Page.routeName,
35 | ),
36 | AppListTile(
37 | title: 'AnimatedWidget',
38 | nextRouteName: AnimatedWidgetPage.routeName,
39 | ),
40 | AppListTile(
41 | title: 'AnimatedBuilder',
42 | nextRouteName: AnimatedBuilderPage.routeName,
43 | ),
44 | AppListTile(
45 | title: 'AnimatedSwitcher',
46 | nextRouteName: AnimatedSwitcher2Page.routeName,
47 | ),
48 | AppListTile(
49 | title: 'ImplicitlyAnimatedWidget',
50 | nextRouteName: ImplicitlyAnimatedWidgetPage.routeName,
51 | ),
52 | AppListTile(
53 | title: 'TweenAnimationBuilder',
54 | nextRouteName: TweenAnimationBuilderPage.routeName,
55 | ),
56 | ],
57 | ),
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/pages/custom/implicitly_animated_widget_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/widget/ghost_fade_tween.dart';
2 | import 'package:animations_app/pages/custom/widget/switch_string_tween.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class ImplicitlyAnimatedWidgetPage extends StatefulWidget {
7 | const ImplicitlyAnimatedWidgetPage({super.key});
8 |
9 | static const routeName = 'ImplicitlyAnimatedWidgetPage';
10 |
11 | @override
12 | State createState() =>
13 | _ImplicitlyAnimatedWidgetPageState();
14 | }
15 |
16 | class _ImplicitlyAnimatedWidgetPageState
17 | extends State {
18 | static const _texts = [
19 | 'First',
20 | 'Second',
21 | 'Third',
22 | ];
23 | static const _colors = [
24 | Colors.black,
25 | Colors.blue,
26 | Colors.red,
27 | ];
28 | var _index = 0;
29 | String get _currentText => _texts[_index % 3];
30 | Color get _currentColor => _colors[_index % 3];
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | return AppScaffold(
35 | title: 'ImplicitlyAnimatedWidget',
36 | floatingActionButton: FloatingActionButton(
37 | onPressed: () {
38 | setState(() {
39 | _index++;
40 | });
41 | },
42 | child: const Icon(Icons.refresh),
43 | ),
44 | child: Center(
45 | child: Headline(
46 | targetColor: _currentColor,
47 | targetString: _currentText,
48 | ),
49 | ),
50 | );
51 | }
52 | }
53 |
54 | class Headline extends ImplicitlyAnimatedWidget {
55 | const Headline({
56 | super.key,
57 | required this.targetColor,
58 | required this.targetString,
59 | }) : super(
60 | duration: const Duration(milliseconds: 1000),
61 | );
62 |
63 | final Color targetColor;
64 | final String targetString;
65 |
66 | @override
67 | AnimatedWidgetBaseState createState() => _HeadlineState();
68 | }
69 |
70 | class _HeadlineState extends AnimatedWidgetBaseState {
71 | GhostFadeTween? _colorTween;
72 | SwitchStringTween? _stringTween;
73 |
74 | @override
75 | Widget build(BuildContext context) {
76 | return Text(
77 | _stringTween!.evaluate(animation),
78 | style: Theme.of(context)
79 | .textTheme
80 | .headline6!
81 | .copyWith(color: _colorTween!.evaluate(animation)),
82 | );
83 | }
84 |
85 | @override
86 | void forEachTween(TweenVisitor visitor) {
87 | _colorTween = visitor(
88 | _colorTween,
89 | widget.targetColor,
90 | (dynamic color) => GhostFadeTween(begin: color as Color),
91 | ) as GhostFadeTween?;
92 |
93 | _stringTween = visitor(
94 | _stringTween,
95 | widget.targetString,
96 | (dynamic string) => SwitchStringTween(begin: string as String),
97 | ) as SwitchStringTween?;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/lib/pages/custom/tween_animation_builder_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class TweenAnimationBuilderPage extends StatefulWidget {
5 | const TweenAnimationBuilderPage({super.key});
6 |
7 | static const routeName = 'TweenAnimationBuilderPage';
8 |
9 | @override
10 | State createState() =>
11 | _TweenAnimationBuilderPageState();
12 | }
13 |
14 | class _TweenAnimationBuilderPageState extends State {
15 | static const _texts = [
16 | 'First',
17 | 'Second',
18 | 'Third',
19 | ];
20 | static const _colors = [
21 | Colors.black,
22 | Colors.blue,
23 | Colors.red,
24 | ];
25 | var _index = 0;
26 | ColoredLabel get _coloredLabel => ColoredLabel(
27 | label: _texts[_index % 3],
28 | color: _colors[_index % 3],
29 | );
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return AppScaffold(
34 | title: 'TweenAnimationBuilder',
35 | floatingActionButton: FloatingActionButton(
36 | onPressed: () {
37 | setState(() {
38 | _index++;
39 | });
40 | },
41 | child: const Icon(Icons.refresh),
42 | ),
43 | child: Center(
44 | child: TweenAnimationBuilder(
45 | tween: ColoredLabelTween(begin: _coloredLabel, end: _coloredLabel),
46 | duration: const Duration(milliseconds: 1000),
47 | builder: (context, coloredLabel, child) {
48 | return Text(
49 | coloredLabel.label,
50 | style: Theme.of(context)
51 | .textTheme
52 | .headline6!
53 | .copyWith(color: coloredLabel.color),
54 | );
55 | },
56 | ),
57 | ),
58 | );
59 | }
60 | }
61 |
62 | class ColoredLabelTween extends Tween {
63 | ColoredLabelTween({
64 | super.begin,
65 | super.end,
66 | });
67 | final _middleColor = Colors.transparent;
68 |
69 | @override
70 | ColoredLabel lerp(double t) => ColoredLabel(
71 | label: t < 0.5 ? begin!.label : end!.label,
72 | color: t < 0.5
73 | ? Color.lerp(begin!.color, _middleColor, t * 2)!
74 | : Color.lerp(_middleColor, end!.color, (t - 0.5) * 2)!,
75 | );
76 | }
77 |
78 | class ColoredLabel {
79 | ColoredLabel({
80 | required this.label,
81 | required this.color,
82 | });
83 |
84 | final String label;
85 | final Color color;
86 |
87 | @override
88 | int get hashCode => Object.hash(label, color);
89 |
90 | @override
91 | bool operator ==(Object other) =>
92 | identical(this, other) ||
93 | other is ColoredLabel &&
94 | runtimeType == other.runtimeType &&
95 | label == other.label &&
96 | color == other.color;
97 | }
98 |
--------------------------------------------------------------------------------
/lib/pages/custom/widget/ghost_fade_tween.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class GhostFadeTween extends Tween {
4 | GhostFadeTween({
5 | super.begin,
6 | super.end,
7 | });
8 | final middle = Colors.transparent;
9 |
10 | @override
11 | Color lerp(double t) {
12 | return t < 0.5
13 | ? Color.lerp(begin, middle, t * 2)!
14 | : Color.lerp(middle, end, (t - 0.5) * 2)!;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/pages/custom/widget/switch_string_tween.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SwitchStringTween extends Tween {
4 | SwitchStringTween({
5 | super.begin,
6 | super.end,
7 | });
8 |
9 | @override
10 | String lerp(double t) => t < 0.5 ? begin! : end!;
11 | }
12 |
--------------------------------------------------------------------------------
/lib/pages/flare/apple_lock_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/widget.dart';
2 | import 'package:flare_flutter/flare_actor.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class AppleLockPage extends StatefulWidget {
6 | const AppleLockPage({super.key});
7 |
8 | static const routeName = 'AppleLock';
9 | @override
10 | State createState() => _AppleLockPageState();
11 | }
12 |
13 | class _AppleLockPageState extends State {
14 | var _isLocked = false;
15 | @override
16 | Widget build(BuildContext context) {
17 | return AppScaffold(
18 | title: 'Flare Example ',
19 | child: ColoredBox(
20 | color: Colors.black,
21 | child: Center(
22 | child: Column(
23 | mainAxisAlignment: MainAxisAlignment.center,
24 | children: [
25 | SizedBox(
26 | width: 300,
27 | height: 300,
28 | child: _isLocked
29 | ? const FlareActor(
30 | 'assets/apple_lock.flr',
31 | animation: 'Untitled',
32 | )
33 | : null,
34 | ),
35 | const SizedBox(height: 16),
36 | ElevatedButton(
37 | onPressed: () {
38 | setState(() => _isLocked = !_isLocked);
39 | },
40 | child: const Text('LOCK'),
41 | )
42 | ],
43 | ),
44 | ),
45 | ),
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/pages/flare/flare_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/flare/apple_lock_page.dart';
2 | import 'package:animations_app/widget/app_list_tile.dart';
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class FlarePage extends StatelessWidget {
7 | const FlarePage({super.key});
8 |
9 | static const routeName = 'Flare';
10 | @override
11 | Widget build(BuildContext context) {
12 | return AppScaffold(
13 | title: 'Flare',
14 | child: ListView(
15 | children: const [
16 | AppListTile(
17 | title: 'Apple Lock',
18 | nextRouteName: AppleLockPage.routeName,
19 | ),
20 | ],
21 | ),
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/README.md:
--------------------------------------------------------------------------------
1 | # Flight Search (Advanced Example)
2 |
3 | ## Credits
4 |
5 | This sample is re-written from this sample:
6 |
7 | - [UI Challenge - Flight Search | Marcin Szałek - Blog](https://marcinszalek.pl/flutter/ui-challenge-flight-search/)
8 | - [MarcinusX/flutter_ui_challenge_flight_search: An advanced UI design implemented in Flutter](https://github.com/MarcinusX/flutter_ui_challenge_flight_search)
9 | - [LICENSE](https://github.com/MarcinusX/flutter_ui_challenge_flight_search/blob/master/LICENSE)
10 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/air_asia_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AirAsiaBar extends StatelessWidget {
4 | const AirAsiaBar({
5 | super.key,
6 | required this.height,
7 | this.leading,
8 | });
9 |
10 | final double height;
11 | final Widget? leading;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Stack(
16 | children: [
17 | _buildBackground(context),
18 | _buildAppBar(context),
19 | ],
20 | );
21 | }
22 |
23 | Widget _buildBackground(BuildContext context) {
24 | return Container(
25 | decoration: BoxDecoration(
26 | gradient: LinearGradient(
27 | begin: Alignment.topCenter,
28 | end: Alignment.bottomCenter,
29 | colors: [
30 | Theme.of(context).primaryColor,
31 | const Color(0xFFE64C85),
32 | ],
33 | ),
34 | ),
35 | height: height,
36 | );
37 | }
38 |
39 | Widget _buildAppBar(BuildContext context) {
40 | return AppBar(
41 | leading: leading,
42 | backgroundColor: Colors.transparent,
43 | elevation: 0,
44 | centerTitle: true,
45 | title: const Text(
46 | 'AirAsia',
47 | style: TextStyle(
48 | fontFamily: 'NothingYouCouldDo',
49 | fontWeight: FontWeight.bold,
50 | ),
51 | ),
52 | );
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/animated_dot.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AnimatedDot extends AnimatedWidget {
4 | const AnimatedDot({
5 | super.key,
6 | required Animation animation,
7 | required this.color,
8 | }) : super(
9 | listenable: animation,
10 | );
11 |
12 | final Color color;
13 | static const double size = 24;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | final animation = super.listenable as Animation;
18 | return Positioned(
19 | top: animation.value,
20 | child: Container(
21 | height: 24,
22 | width: 24,
23 | decoration: BoxDecoration(
24 | color: Colors.white,
25 | shape: BoxShape.circle,
26 | border: Border.all(
27 | color: const Color(0xFFDDDDDD),
28 | ),
29 | ),
30 | child: Container(
31 | margin: const EdgeInsets.all(4),
32 | decoration: BoxDecoration(
33 | color: color,
34 | shape: BoxShape.circle,
35 | ),
36 | ),
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/animated_plane_icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AnimatedPlaneIcon extends StatelessWidget {
4 | const AnimatedPlaneIcon({
5 | super.key,
6 | required this.size,
7 | required this.scaleAnimation,
8 | });
9 |
10 | final double size;
11 | final Animation scaleAnimation;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return ScaleTransition(
16 | alignment: Alignment.bottomCenter,
17 | scale: scaleAnimation,
18 | child: Icon(
19 | Icons.airplanemode_active,
20 | color: Theme.of(context).primaryColor,
21 | size: 36,
22 | ),
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/content_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/flight_search/multicity_input.dart';
2 | import 'package:animations_app/pages/flight_search/price_tab.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class ContentCard extends StatelessWidget {
6 | const ContentCard({
7 | super.key,
8 | required this.showInput,
9 | required this.onCompleted,
10 | });
11 |
12 | final bool showInput;
13 | final void Function() onCompleted;
14 |
15 | static const _tabs = [
16 | Tab(text: 'Flight'),
17 | Tab(text: 'Train'),
18 | Tab(text: 'Bus'),
19 | ];
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return Card(
24 | elevation: 4,
25 | margin: const EdgeInsets.all(8),
26 | child: DefaultTabController(
27 | length: _tabs.length,
28 | child: Column(
29 | children: [
30 | _buildTabBar(),
31 | Expanded(
32 | child: TabBarView(
33 | children: _tabs.map((_) => _buildTabContent()).toList(),
34 | ),
35 | ),
36 | ],
37 | ),
38 | ),
39 | );
40 | }
41 |
42 | Widget _buildTabBar() {
43 | return Stack(
44 | children: [
45 | Positioned.fill(
46 | top: null,
47 | child: Container(
48 | height: 2,
49 | color: const Color(0xFFEEEEEE),
50 | ),
51 | ),
52 | const TabBar(
53 | tabs: _tabs,
54 | labelColor: Colors.black,
55 | unselectedLabelColor: Colors.grey,
56 | ),
57 | ],
58 | );
59 | }
60 |
61 | Widget _buildTabContent() {
62 | return AnimatedSwitcher(
63 | duration: const Duration(milliseconds: 200),
64 | child: SizedBox.expand(
65 | child: showInput
66 | ? const SingleChildScrollView(
67 | physics: AlwaysScrollableScrollPhysics(),
68 | child: MulticityInput(),
69 | )
70 | : PriceTab(onCompleted: onCompleted),
71 | ),
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/fade_route.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class FadeRoute extends MaterialPageRoute {
4 | FadeRoute({
5 | required super.builder,
6 | }) : super(
7 | fullscreenDialog: true,
8 | );
9 |
10 | @override
11 | Duration get transitionDuration => const Duration(milliseconds: 100);
12 |
13 | @override
14 | Widget buildTransitions(
15 | BuildContext context,
16 | Animation animation,
17 | Animation secondaryAnimation,
18 | Widget child,
19 | ) {
20 | if (settings.name == '/') {
21 | return child;
22 | }
23 | return FadeTransition(
24 | opacity: animation,
25 | child: child,
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/flight_search_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/app.dart';
2 | import 'package:animations_app/pages/flight_search/air_asia_bar.dart';
3 | import 'package:animations_app/pages/flight_search/content_card.dart';
4 | import 'package:animations_app/pages/flight_search/fade_route.dart';
5 | import 'package:animations_app/pages/flight_search/rounded_button.dart';
6 | import 'package:animations_app/pages/flight_search/ticker_page.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:keyboard_visibility/keyboard_visibility.dart';
9 |
10 | enum FlightSearchMode { normal, plane, done }
11 |
12 | class FlightSearchPage extends StatefulWidget {
13 | const FlightSearchPage({super.key});
14 |
15 | static const routeName = 'FlightSearchPage';
16 |
17 | @override
18 | State createState() => _FlightSearchPageState();
19 | }
20 |
21 | class _FlightSearchPageState extends State {
22 | var _mode = FlightSearchMode.normal;
23 | var _isKeyboardVisible = false;
24 | var _selectedButtonIndex = 2;
25 | final _keyboardVisibilityNotification = KeyboardVisibilityNotification();
26 | late final int _keyboardVisibilityNotificationSubscription;
27 |
28 | @override
29 | void initState() {
30 | super.initState();
31 | _keyboardVisibilityNotificationSubscription =
32 | _keyboardVisibilityNotification.addNewListener(
33 | onChange: (visible) {
34 | setState(() {
35 | _isKeyboardVisible = visible;
36 | });
37 | },
38 | );
39 | }
40 |
41 | @override
42 | void dispose() {
43 | _keyboardVisibilityNotification
44 | .removeListener(_keyboardVisibilityNotificationSubscription);
45 | super.dispose();
46 | }
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | final top = MediaQuery.of(context).padding.top;
51 | return Scaffold(
52 | body: Stack(
53 | children: [
54 | AirAsiaBar(
55 | height: top + 200,
56 | leading: IconButton(
57 | icon: const BackButtonIcon(),
58 | tooltip: MaterialLocalizations.of(context).backButtonTooltip,
59 | onPressed: () {
60 | rootNavigatorKey.currentState!.pop();
61 | },
62 | ),
63 | ),
64 | Padding(
65 | padding: EdgeInsets.only(top: top + 40.0),
66 | child: Column(
67 | children: [
68 | _buildButtonsRow(),
69 | Expanded(
70 | child: ContentCard(
71 | onCompleted: () {
72 | setState(() {
73 | _mode = FlightSearchMode.done;
74 | });
75 | },
76 | showInput: _mode == FlightSearchMode.normal,
77 | ),
78 | ),
79 | ],
80 | ),
81 | ),
82 | ],
83 | ),
84 | floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
85 | floatingActionButton: _buildFab(),
86 | );
87 | }
88 |
89 | Widget? _buildFab() {
90 | if (_isKeyboardVisible) {
91 | return null;
92 | }
93 | switch (_mode) {
94 | case FlightSearchMode.normal:
95 | return FloatingActionButton(
96 | onPressed: () {
97 | setState(() {
98 | _mode = FlightSearchMode.plane;
99 | });
100 | },
101 | child: const Icon(
102 | Icons.timeline,
103 | size: 36,
104 | ),
105 | );
106 | case FlightSearchMode.plane:
107 | return null;
108 | case FlightSearchMode.done:
109 | return FloatingActionButton(
110 | onPressed: () {
111 | Navigator.of(context).push(
112 | FadeRoute(builder: (context) => const TicketsPage()),
113 | );
114 | },
115 | child: const Icon(
116 | Icons.check,
117 | size: 36,
118 | ),
119 | );
120 | }
121 | }
122 |
123 | Widget _buildButtonsRow() {
124 | return Padding(
125 | padding: const EdgeInsets.all(8),
126 | child: Row(
127 | children: [
128 | RoundedButton(
129 | text: 'ONE WAY',
130 | selected: _selectedButtonIndex == 0,
131 | onPressed: () {
132 | setState(() => _selectedButtonIndex = 0);
133 | },
134 | ),
135 | RoundedButton(
136 | text: 'ROUND',
137 | selected: _selectedButtonIndex == 1,
138 | onPressed: () {
139 | setState(() => _selectedButtonIndex = 1);
140 | },
141 | ),
142 | RoundedButton(
143 | text: 'MULTICITY',
144 | selected: _selectedButtonIndex == 2,
145 | onPressed: () {
146 | setState(() => _selectedButtonIndex = 2);
147 | },
148 | ),
149 | ],
150 | ),
151 | );
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/flight_stop.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | @immutable
4 | class FlightStop {
5 | const FlightStop({
6 | required this.from,
7 | required this.to,
8 | required this.date,
9 | required this.duration,
10 | required this.price,
11 | required this.fromToTime,
12 | });
13 |
14 | final String from;
15 | final String to;
16 | final String date;
17 | final String duration;
18 | final String price;
19 | final String fromToTime;
20 | }
21 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/flight_stop_ticker.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | @immutable
4 | class FlightStopTicket {
5 | const FlightStopTicket({
6 | required this.from,
7 | required this.fromShort,
8 | required this.to,
9 | required this.toShort,
10 | required this.flightNumber,
11 | });
12 | final String from;
13 | final String fromShort;
14 | final String to;
15 | final String toShort;
16 | final String flightNumber;
17 | }
18 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/multicity_input.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MulticityInput extends StatefulWidget {
4 | const MulticityInput({super.key});
5 |
6 | static const double _rightMargin = 64;
7 | static const double _rowSpace = 8;
8 | static const rowSpaceBox = SizedBox(height: _rowSpace);
9 |
10 | @override
11 | State createState() => _MulticityInputState();
12 | }
13 |
14 | class _MulticityInputState extends State {
15 | @override
16 | Widget build(BuildContext context) {
17 | return Padding(
18 | padding: const EdgeInsets.all(16),
19 | child: Column(
20 | children: [
21 | _buildFrom(),
22 | MulticityInput.rowSpaceBox,
23 | _buildTo1(),
24 | MulticityInput.rowSpaceBox,
25 | _buildTo2(),
26 | MulticityInput.rowSpaceBox,
27 | _buildPassengers(),
28 | MulticityInput.rowSpaceBox,
29 | _buildDateRow(),
30 | ],
31 | ),
32 | );
33 | }
34 |
35 | Widget _buildFrom() {
36 | return Padding(
37 | padding: const EdgeInsets.only(right: MulticityInput._rightMargin),
38 | child: _buildTextField(
39 | icon: Icons.flight_takeoff,
40 | labelText: 'From',
41 | ),
42 | );
43 | }
44 |
45 | Widget _buildTo1() {
46 | return Padding(
47 | padding: const EdgeInsets.only(right: MulticityInput._rightMargin),
48 | child: _buildTextField(
49 | icon: Icons.flight_land,
50 | labelText: 'To',
51 | ),
52 | );
53 | }
54 |
55 | Row _buildTo2() {
56 | return Row(
57 | children: [
58 | Expanded(
59 | child: _buildTextField(
60 | icon: Icons.flight_land,
61 | labelText: 'To',
62 | ),
63 | ),
64 | SizedBox(
65 | width: MulticityInput._rightMargin,
66 | child: IconButton(
67 | onPressed: () {},
68 | icon: const Icon(
69 | Icons.add_circle_outline,
70 | color: Colors.grey,
71 | ),
72 | ),
73 | ),
74 | ],
75 | );
76 | }
77 |
78 | Widget _buildPassengers() {
79 | return Padding(
80 | padding: const EdgeInsets.only(right: MulticityInput._rightMargin),
81 | child: _buildTextField(
82 | icon: Icons.person,
83 | labelText: 'Passengers',
84 | ),
85 | );
86 | }
87 |
88 | Row _buildDateRow() {
89 | return Row(
90 | children: [
91 | Expanded(
92 | child: _buildTextField(
93 | icon: Icons.date_range,
94 | labelText: 'Departure',
95 | ),
96 | ),
97 | Expanded(
98 | child: _buildTextField(
99 | labelText: 'Arrival',
100 | ),
101 | ),
102 | ],
103 | );
104 | }
105 |
106 | TextFormField _buildTextField({
107 | required String labelText,
108 | IconData? icon,
109 | }) {
110 | return TextFormField(
111 | decoration: InputDecoration(
112 | icon: Icon(
113 | icon,
114 | color: Theme.of(context).primaryColor,
115 | ),
116 | labelText: labelText,
117 | ),
118 | );
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/price_tab.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/flight_search/animated_dot.dart';
2 | import 'package:animations_app/pages/flight_search/animated_plane_icon.dart';
3 | import 'package:animations_app/pages/flight_search/flight_stop.dart';
4 | import 'package:animations_app/pages/flight_search/flight_stop_card.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | class PriceTab extends StatefulWidget {
8 | const PriceTab({
9 | super.key,
10 | required this.onCompleted,
11 | });
12 |
13 | final void Function() onCompleted;
14 |
15 | @override
16 | State createState() => _PriceTabState();
17 | }
18 |
19 | class _PriceTabState extends State with TickerProviderStateMixin {
20 | late final AnimationController _planeSizeController = AnimationController(
21 | vsync: this,
22 | duration: const Duration(milliseconds: 340),
23 | );
24 | late final AnimationController _planeTravelController = AnimationController(
25 | vsync: this,
26 | duration: const Duration(milliseconds: 400),
27 | );
28 | late final AnimationController _dotsAnimationController = AnimationController(
29 | vsync: this,
30 | duration: const Duration(milliseconds: 500),
31 | );
32 | late final Animation _planeScaleAnimation = _planeSizeController
33 | .drive(
34 | CurveTween(curve: Curves.easeOut),
35 | )
36 | .drive(
37 | Tween(
38 | begin: 5 / 3,
39 | end: 1,
40 | ),
41 | );
42 |
43 | static const double _initialPlanePaddingBottom = 16;
44 | static const double _minPlanePaddingTop = 16;
45 | static const double _planeSize = 36;
46 | static const double _cardHeight = 80;
47 | static const _flightStops = [
48 | FlightStop(
49 | from: 'JFK',
50 | to: 'ORY',
51 | date: 'JUN 05',
52 | duration: '6h 25m',
53 | price: '\$851',
54 | fromToTime: '9:26 am - 3:43 pm',
55 | ),
56 | FlightStop(
57 | from: 'MRG',
58 | to: 'FTB',
59 | date: 'JUN 20',
60 | duration: '6h 25m',
61 | price: '\$532',
62 | fromToTime: '9:26 am - 3:43 pm',
63 | ),
64 | FlightStop(
65 | from: 'ERT',
66 | to: 'TVS',
67 | date: 'JUN 20',
68 | duration: '6h 25m',
69 | price: '\$718',
70 | fromToTime: '9:26 am - 3:43 pm',
71 | ),
72 | FlightStop(
73 | from: 'KKR',
74 | to: 'RTY',
75 | date: 'JUN 20',
76 | duration: '6h 25m',
77 | price: '\$663',
78 | fromToTime: '9:26 am - 3:43 pm',
79 | ),
80 | ];
81 | final _stopKeys =
82 | _flightStops.map((s) => GlobalKey()).toList();
83 |
84 | @override
85 | void initState() {
86 | super.initState();
87 |
88 | _forwardAnimation();
89 | }
90 |
91 | Future _forwardAnimation() async {
92 | await _planeSizeController.forward();
93 | // ignore: unawaited_futures
94 | Future.delayed(const Duration(milliseconds: 500))
95 | .then((_) => _planeTravelController.forward());
96 | // ignore: unawaited_futures
97 | Future.delayed(const Duration(milliseconds: 700)).then((_) async {
98 | await _dotsAnimationController.forward();
99 | await _animateFlightStopCards();
100 | });
101 | }
102 |
103 | Future _animateFlightStopCards() async {
104 | for (final stopKey in _stopKeys) {
105 | await Future.delayed(const Duration(milliseconds: 250));
106 | // ignore: unawaited_futures
107 | stopKey.currentState?.runAnimation();
108 | }
109 | await Future.delayed(const Duration(milliseconds: 100));
110 | widget.onCompleted();
111 | }
112 |
113 | @override
114 | void dispose() {
115 | _planeSizeController.dispose();
116 | _planeTravelController.dispose();
117 | _dotsAnimationController.dispose();
118 | super.dispose();
119 | }
120 |
121 | @override
122 | Widget build(BuildContext context) {
123 | return LayoutBuilder(
124 | builder: (context, constraints) {
125 | final flightStopTweenMap = _flightStops.asMap().map((index, stop) {
126 | const minMarginTop =
127 | _minPlanePaddingTop + _planeSize + (0.8 * _cardHeight);
128 | final finalMarginTop = index * (0.8 * _cardHeight) + minMarginTop;
129 | return MapEntry(
130 | stop,
131 | Tween(
132 | begin: constraints.maxHeight,
133 | end: finalMarginTop,
134 | ),
135 | );
136 | });
137 | return Stack(
138 | alignment: Alignment.center,
139 | children: [
140 | _buildPlane(constraints: constraints),
141 | ..._flightStops.map(
142 | (stop) => _buildStopCard(
143 | stop: stop,
144 | tween: flightStopTweenMap[stop]!,
145 | ),
146 | ),
147 | ..._flightStops.map(
148 | (stop) => _mapFlightStopToDot(
149 | stop: stop,
150 | tween: flightStopTweenMap[stop]!,
151 | ),
152 | ),
153 | ],
154 | );
155 | },
156 | );
157 | }
158 |
159 | Widget _buildPlane({
160 | required BoxConstraints constraints,
161 | }) {
162 | final beginTop =
163 | constraints.maxHeight - (_initialPlanePaddingBottom + _planeSize);
164 | final planeTravelAnimation = _planeTravelController
165 | .drive(CurveTween(curve: Curves.fastOutSlowIn))
166 | .drive(
167 | Tween(
168 | begin: beginTop,
169 | end: _minPlanePaddingTop,
170 | ),
171 | );
172 | return AnimatedBuilder(
173 | animation: planeTravelAnimation,
174 | builder: (context, child) => Positioned(
175 | top: planeTravelAnimation.value,
176 | child: child!,
177 | ),
178 | child: Column(
179 | children: [
180 | AnimatedPlaneIcon(
181 | size: _planeSize,
182 | scaleAnimation: _planeScaleAnimation,
183 | ),
184 | Container(
185 | width: 2,
186 | height: _flightStops.length * _cardHeight * 0.8,
187 | color: const Color.fromARGB(255, 200, 200, 200),
188 | )
189 | ],
190 | ),
191 | );
192 | }
193 |
194 | Widget _mapFlightStopToDot({
195 | required FlightStop stop,
196 | required Tween tween,
197 | }) {
198 | final index = _flightStops.indexOf(stop);
199 | final start = 0.2 * _flightStops.indexOf(stop);
200 | final animation = _dotsAnimationController
201 | .drive(
202 | CurveTween(
203 | curve: Interval(
204 | start,
205 | start + 0.4,
206 | curve: Curves.easeOut,
207 | ),
208 | ),
209 | )
210 | .drive(tween);
211 |
212 | final isStartOrEnd = index == 0 || index == _flightStops.length - 1;
213 | final color = isStartOrEnd ? Theme.of(context).primaryColor : Colors.green;
214 | return AnimatedDot(
215 | animation: animation,
216 | color: color,
217 | );
218 | }
219 |
220 | Widget _buildStopCard({
221 | required FlightStop stop,
222 | required Tween tween,
223 | }) {
224 | final index = _flightStops.indexOf(stop);
225 | final topMargin =
226 | tween.end! - 0.5 * (FlightStopCard.height - AnimatedDot.size);
227 | final isLeft = index.isOdd;
228 | return Align(
229 | alignment: Alignment.topCenter,
230 | child: Padding(
231 | padding: EdgeInsets.only(top: topMargin),
232 | child: Row(
233 | crossAxisAlignment: CrossAxisAlignment.start,
234 | children: [
235 | isLeft ? Container() : Expanded(child: Container()),
236 | Expanded(
237 | child: FlightStopCard(
238 | key: _stopKeys[index],
239 | flightStop: stop,
240 | isLeft: isLeft,
241 | ),
242 | ),
243 | !isLeft ? Container() : Expanded(child: Container()),
244 | ],
245 | ),
246 | ),
247 | );
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/rounded_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class RoundedButton extends StatelessWidget {
4 | const RoundedButton({
5 | super.key,
6 | required this.text,
7 | this.selected = false,
8 | this.onPressed,
9 | });
10 |
11 | final String text;
12 | final bool selected;
13 | final GestureTapCallback? onPressed;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Expanded(
18 | child: Padding(
19 | padding: const EdgeInsets.all(4),
20 | child: AnimatedCrossFade(
21 | firstChild: _buildSelectedButton(context),
22 | secondChild: _buildUnselectedButton(),
23 | crossFadeState:
24 | selected ? CrossFadeState.showFirst : CrossFadeState.showSecond,
25 | duration: const Duration(milliseconds: 200),
26 | ),
27 | ),
28 | );
29 | }
30 |
31 | Widget _buildUnselectedButton() {
32 | const color = Colors.white;
33 | return TextButton(
34 | style: TextButton.styleFrom(
35 | side: const BorderSide(color: color),
36 | primary: Colors.white,
37 | onSurface: color,
38 | shape: const StadiumBorder(),
39 | ),
40 | onPressed: onPressed,
41 | child: Center(child: Text(text)),
42 | );
43 | }
44 |
45 | Widget _buildSelectedButton(BuildContext context) {
46 | final textColor = Theme.of(context).primaryColor;
47 | return ElevatedButton(
48 | style: ElevatedButton.styleFrom(
49 | elevation: 0,
50 | primary: Colors.white,
51 | onPrimary: textColor,
52 | shape: const StadiumBorder(),
53 | ),
54 | onPressed: onPressed ?? () {},
55 | child: Center(child: Text(text)),
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/ticker_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/app.dart';
2 | import 'package:animations_app/pages/flight_search/air_asia_bar.dart';
3 | import 'package:animations_app/pages/flight_search/flight_stop_ticker.dart';
4 | import 'package:animations_app/pages/flight_search/ticket_card.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | class TicketsPage extends StatefulWidget {
8 | const TicketsPage({super.key});
9 |
10 | @override
11 | State createState() => _TicketsPageState();
12 | }
13 |
14 | class _TicketsPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | static const stops = [
17 | FlightStopTicket(
18 | from: 'Sahara',
19 | fromShort: 'SHE',
20 | to: 'Macao',
21 | toShort: 'MAC',
22 | flightNumber: 'SE2341',
23 | ),
24 | FlightStopTicket(
25 | from: 'Macao',
26 | fromShort: 'MAC',
27 | to: 'Cape Verde',
28 | toShort: 'CAP',
29 | flightNumber: 'KU2342',
30 | ),
31 | FlightStopTicket(
32 | from: 'Cape Verde',
33 | fromShort: 'CAP',
34 | to: 'Ireland',
35 | toShort: 'IRE',
36 | flightNumber: 'KR3452',
37 | ),
38 | FlightStopTicket(
39 | from: 'Ireland',
40 | fromShort: 'IRE',
41 | to: 'Sahara',
42 | toShort: 'SHE',
43 | flightNumber: 'MR4321',
44 | ),
45 | ];
46 | late final AnimationController _cardEntranceAnimationController =
47 | AnimationController(
48 | vsync: this,
49 | duration: const Duration(milliseconds: 1100),
50 | );
51 | late final Map> _ticketAnimations =
52 | stops.asMap().map((index, stop) {
53 | final start = index * 0.1;
54 | return MapEntry(
55 | stop,
56 | _cardEntranceAnimationController
57 | .drive(
58 | CurveTween(
59 | curve: Interval(
60 | start,
61 | start + 0.6,
62 | curve: Curves.decelerate,
63 | ),
64 | ),
65 | )
66 | .drive(
67 | Tween(begin: 800, end: 0),
68 | ),
69 | );
70 | });
71 |
72 | @override
73 | void initState() {
74 | super.initState();
75 |
76 | _runAnimation();
77 | }
78 |
79 | Future _runAnimation() async {
80 | await _cardEntranceAnimationController.forward();
81 | setState(() {});
82 | }
83 |
84 | @override
85 | void dispose() {
86 | _cardEntranceAnimationController.dispose();
87 | super.dispose();
88 | }
89 |
90 | @override
91 | Widget build(BuildContext context) {
92 | return Scaffold(
93 | body: Stack(
94 | children: [
95 | const AirAsiaBar(
96 | height: 180,
97 | ),
98 | Positioned.fill(
99 | top: MediaQuery.of(context).padding.top + 64,
100 | child: SingleChildScrollView(
101 | child: Column(
102 | children: _buildTickets().toList(),
103 | ),
104 | ),
105 | )
106 | ],
107 | ),
108 | floatingActionButton: _buildFab(),
109 | floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
110 | );
111 | }
112 |
113 | Iterable _buildTickets() {
114 | return stops.map(
115 | (stop) {
116 | final animation = _ticketAnimations[stop]!;
117 | return AnimatedBuilder(
118 | animation: animation,
119 | builder: (context, child) => Transform.translate(
120 | offset: Offset(0, animation.value),
121 | child: child,
122 | ),
123 | child: Padding(
124 | padding: const EdgeInsets.symmetric(
125 | vertical: 4,
126 | horizontal: 8,
127 | ),
128 | child: TicketCard(stop: stop),
129 | ),
130 | );
131 | },
132 | );
133 | }
134 |
135 | Widget? _buildFab() {
136 | if (_cardEntranceAnimationController.status != AnimationStatus.completed) {
137 | return null;
138 | }
139 | return FloatingActionButton(
140 | onPressed: () => rootNavigatorKey.currentState!.pop(),
141 | child: const Icon(Icons.fingerprint),
142 | );
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/lib/pages/flight_search/ticket_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/flight_search/flight_stop_ticker.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class TicketCard extends StatelessWidget {
5 | const TicketCard({
6 | super.key,
7 | required this.stop,
8 | });
9 |
10 | final FlightStopTicket stop;
11 | static const airportNameStyle = TextStyle(
12 | fontSize: 16,
13 | fontWeight: FontWeight.w600,
14 | );
15 | static const airportShortNameStyle = TextStyle(
16 | fontSize: 36,
17 | fontWeight: FontWeight.w200,
18 | );
19 | static const flightNumberStyle = TextStyle(
20 | fontSize: 12,
21 | fontWeight: FontWeight.w500,
22 | );
23 |
24 | @override
25 | Widget build(BuildContext context) {
26 | return ClipPath(
27 | clipper: TicketClipper(radius: 10),
28 | child: Material(
29 | elevation: 4,
30 | shadowColor: const Color(0x30E5E5E5),
31 | color: Colors.transparent,
32 | child: ClipPath(
33 | clipper: TicketClipper(radius: 12),
34 | child: Card(
35 | elevation: 0,
36 | margin: const EdgeInsets.all(2),
37 | child: _buildCardContent(context),
38 | ),
39 | ),
40 | ),
41 | );
42 | }
43 |
44 | Widget _buildCardContent(BuildContext context) {
45 | return SizedBox(
46 | height: 104,
47 | child: Row(
48 | children: [
49 | Expanded(
50 | child: _buildLocation(
51 | name: stop.from,
52 | nameShort: stop.fromShort,
53 | ),
54 | ),
55 | _buildFlightNumber(context),
56 | Expanded(
57 | child: _buildLocation(
58 | name: stop.to,
59 | nameShort: stop.toShort,
60 | ),
61 | ),
62 | ],
63 | ),
64 | );
65 | }
66 |
67 | Widget _buildFlightNumber(BuildContext context) {
68 | return Column(
69 | mainAxisAlignment: MainAxisAlignment.center,
70 | children: [
71 | Padding(
72 | padding: const EdgeInsets.only(bottom: 8),
73 | child: Icon(
74 | Icons.airplanemode_active,
75 | color: Theme.of(context).primaryColor,
76 | ),
77 | ),
78 | Text(
79 | stop.flightNumber,
80 | style: flightNumberStyle,
81 | ),
82 | ],
83 | );
84 | }
85 |
86 | Widget _buildLocation({
87 | required String name,
88 | required String nameShort,
89 | }) {
90 | return Column(
91 | mainAxisAlignment: MainAxisAlignment.center,
92 | children: [
93 | Padding(
94 | padding: const EdgeInsets.only(bottom: 8),
95 | child: Text(
96 | name,
97 | style: airportNameStyle,
98 | ),
99 | ),
100 | Text(
101 | nameShort,
102 | style: airportShortNameStyle,
103 | ),
104 | ],
105 | );
106 | }
107 | }
108 |
109 | class TicketClipper extends CustomClipper {
110 | TicketClipper({
111 | required this.radius,
112 | });
113 |
114 | final double radius;
115 |
116 | @override
117 | Path getClip(Size size) {
118 | return Path()
119 | ..lineTo(0, size.height)
120 | ..lineTo(size.width, size.height)
121 | ..lineTo(size.width, 0)
122 | ..addOval(Rect.fromCircle(
123 | center: Offset(0, size.height / 2),
124 | radius: radius,
125 | ),)
126 | ..addOval(Rect.fromCircle(
127 | center: Offset(size.width, size.height / 2),
128 | radius: radius,
129 | ),);
130 | }
131 |
132 | @override
133 | bool shouldReclip(TicketClipper oldClipper) => oldClipper.radius != radius;
134 | }
135 |
--------------------------------------------------------------------------------
/lib/pages/home/home_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/custom/custom_page.dart';
2 | import 'package:animations_app/pages/flare/flare_page.dart';
3 | import 'package:animations_app/pages/flight_search/flight_search_page.dart';
4 | import 'package:animations_app/pages/implicitly_animated/implicitly_animated_page.dart';
5 | import 'package:animations_app/pages/transition/transition_page.dart';
6 | import 'package:animations_app/widget/app_list_tile.dart';
7 | import 'package:animations_app/widget/app_scaffold.dart';
8 | import 'package:flutter/material.dart';
9 |
10 | class HomePage extends StatelessWidget {
11 | const HomePage({super.key});
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return AppScaffold(
16 | title: 'Animation',
17 | child: ListView(
18 | children: const [
19 | AppListTile(
20 | title: 'ImplicitlyAnimated',
21 | nextRouteName: ImplicitlyAnimatedPage.routeName,
22 | ),
23 | AppListTile(
24 | title: 'Transition',
25 | nextRouteName: TransitionPage.routeName,
26 | ),
27 | AppListTile(
28 | title: 'Flight Search (Advanced Example)',
29 | nextRouteName: FlightSearchPage.routeName,
30 | ),
31 | AppListTile(
32 | title: 'Custom',
33 | nextRouteName: CustomPage.routeName,
34 | ),
35 | AppListTile(
36 | title: 'Flare',
37 | nextRouteName: FlarePage.routeName,
38 | ),
39 | ],
40 | ),
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_align.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/animation_object.dart';
2 | import 'package:animations_app/widget/app_scaffold.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class AnimatedAlignPage extends StatefulWidget {
6 | const AnimatedAlignPage({super.key});
7 |
8 | static const routeName = 'animatedAlign';
9 |
10 | @override
11 | State createState() => _AnimatedAlignPageState();
12 | }
13 |
14 | class _AnimatedAlignPageState extends State {
15 | static const _alignments = [
16 | Alignment.topLeft,
17 | Alignment.topRight,
18 | Alignment.bottomRight,
19 | Alignment.bottomLeft,
20 | ];
21 |
22 | var _index = 0;
23 | AlignmentGeometry get _alignment => _alignments[_index % _alignments.length];
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | return AppScaffold(
28 | title: 'AnimatedAlign',
29 | floatingActionButton: FloatingActionButton(
30 | onPressed: () {
31 | setState(() {
32 | _index++;
33 | });
34 | },
35 | child: const Icon(Icons.refresh),
36 | ),
37 | child: AnimatedAlign(
38 | alignment: _alignment,
39 | duration: const Duration(milliseconds: 500),
40 | curve: Curves.easeInOut,
41 | child: const AnimationObject(),
42 | ),
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_container.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/animation_object.dart';
2 | import 'package:animations_app/widget/app_scaffold.dart';
3 | import 'package:flutter/material.dart';
4 |
5 | class AnimatedContainerPage extends StatefulWidget {
6 | const AnimatedContainerPage({super.key});
7 |
8 | static const routeName = 'animatedContainer';
9 |
10 | @override
11 | State createState() => _AnimatedContainerPageState();
12 | }
13 |
14 | class _AnimatedContainerPageState extends State {
15 | static const _alignments = [
16 | Alignment.topLeft,
17 | Alignment.topRight,
18 | Alignment.bottomRight,
19 | Alignment.bottomLeft,
20 | ];
21 | static const _colors = [
22 | Colors.red,
23 | Colors.green,
24 | Colors.blue,
25 | Colors.yellow,
26 | ];
27 |
28 | var _index = 0;
29 | AlignmentGeometry get _alignment => _alignments[_index % _alignments.length];
30 | Color get _color => _colors[_index % _colors.length];
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | return AppScaffold(
35 | title: 'AnimatedContainer',
36 | floatingActionButton: FloatingActionButton(
37 | onPressed: () {
38 | setState(() {
39 | _index++;
40 | });
41 | },
42 | child: const Icon(Icons.refresh),
43 | ),
44 | child: AnimatedContainer(
45 | alignment: _alignment,
46 | color: _color,
47 | margin: EdgeInsets.all(20 * ((3 - _index).toDouble() % 4)),
48 | padding: EdgeInsets.all(20 * (_index.toDouble() % 4)),
49 | duration: const Duration(milliseconds: 500),
50 | curve: Curves.easeInOut,
51 | child: const AnimationObject(),
52 | ),
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_cross_fade.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // MEMO: ImplicitlyAnimatedWidgetの派生クラスではない
5 | class AnimatedCrossFadePage extends StatefulWidget {
6 | const AnimatedCrossFadePage({super.key});
7 |
8 | static const routeName = 'animatedCrossFade';
9 |
10 | @override
11 | State createState() => _AnimatedCrossFadePageState();
12 | }
13 |
14 | class _AnimatedCrossFadePageState extends State {
15 | var _showFirst = true;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return AppScaffold(
20 | title: 'AnimatedCrossFade',
21 | floatingActionButton: FloatingActionButton(
22 | onPressed: () {
23 | setState(() {
24 | _showFirst = !_showFirst;
25 | });
26 | },
27 | child: const Icon(Icons.refresh),
28 | ),
29 | child: Center(
30 | child: AnimatedCrossFade(
31 | firstChild: Image.asset('assets/love.png'),
32 | secondChild: Image.asset('assets/love_gray.png'),
33 | duration: const Duration(milliseconds: 500),
34 | crossFadeState:
35 | _showFirst ? CrossFadeState.showFirst : CrossFadeState.showSecond,
36 | ),
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_default_text_style.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedDefaultTextStylePage extends StatefulWidget {
5 | const AnimatedDefaultTextStylePage({super.key});
6 |
7 | static const routeName = 'AnimatedDefaultTextStyle';
8 |
9 | @override
10 | State createState() =>
11 | _AnimatedDefaultTextStylePageState();
12 | }
13 |
14 | class _AnimatedDefaultTextStylePageState
15 | extends State {
16 | var _index = 0;
17 | TextStyle get _textStyle {
18 | switch (_index % 4) {
19 | case 0:
20 | return Theme.of(context)
21 | .textTheme
22 | .headline4!
23 | .copyWith(color: Colors.red);
24 | case 1:
25 | return Theme.of(context)
26 | .textTheme
27 | .headline3!
28 | .copyWith(color: Colors.green);
29 | case 2:
30 | return Theme.of(context)
31 | .textTheme
32 | .headline2!
33 | .copyWith(color: Colors.blue);
34 | case 3:
35 | return Theme.of(context)
36 | .textTheme
37 | .headline1!
38 | .copyWith(color: Colors.orange);
39 | }
40 | assert(false);
41 | return const TextStyle();
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) {
46 | return AppScaffold(
47 | title: 'AnimatedDefaultTextStyle',
48 | floatingActionButton: FloatingActionButton(
49 | onPressed: () {
50 | setState(() {
51 | _index++;
52 | });
53 | },
54 | child: const Icon(Icons.refresh),
55 | ),
56 | child: Center(
57 | child: AnimatedDefaultTextStyle(
58 | duration: const Duration(milliseconds: 500),
59 | curve: Curves.easeInOut,
60 | style: _textStyle,
61 | child: const Text('Flutter'),
62 | ),
63 | ),
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_icon.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // MEMO: ImplicitlyAnimatedWidgetの派生クラスではない
5 | class AnimatedIconPage extends StatefulWidget {
6 | const AnimatedIconPage({super.key});
7 |
8 | static const routeName = 'AnimatedIcon';
9 |
10 | @override
11 | State createState() => _AnimatedIconPageState();
12 | }
13 |
14 | class _AnimatedIconPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 | var _playButtonEnabled = true;
21 |
22 | @override
23 | void dispose() {
24 | _animationController.dispose();
25 | super.dispose();
26 | }
27 |
28 | Future _play() async {
29 | setState(() {
30 | _playButtonEnabled = false;
31 | });
32 | await _animationController.forward(from: 0);
33 | await Future.delayed(const Duration(seconds: 2));
34 | await _animationController.reverse();
35 | setState(() {
36 | _playButtonEnabled = true;
37 | });
38 | }
39 |
40 | @override
41 | Widget build(BuildContext context) {
42 | return AppScaffold(
43 | title: 'AnimatedIcon',
44 | floatingActionButton: _playButtonEnabled
45 | ? FloatingActionButton(
46 | onPressed: _play,
47 | child: const Icon(Icons.play_arrow),
48 | )
49 | : null,
50 | child: Center(
51 | child: Row(
52 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
53 | children: [
54 | _buildAnimatedIcon(AnimatedIcons.add_event, label: 'add_event'),
55 | _buildAnimatedIcon(AnimatedIcons.pause_play, label: 'pause_play'),
56 | _buildAnimatedIcon(AnimatedIcons.close_menu, label: 'close_menu'),
57 | _buildAnimatedIcon(
58 | AnimatedIcons.ellipsis_search,
59 | label: 'ellipsis_search',
60 | ),
61 | ],
62 | ),
63 | ),
64 | );
65 | }
66 |
67 | Widget _buildAnimatedIcon(AnimatedIconData icon, {required String label}) {
68 | return Column(
69 | mainAxisAlignment: MainAxisAlignment.center,
70 | children: [
71 | AnimatedIcon(
72 | icon: icon,
73 | progress: _animationController,
74 | ),
75 | const SizedBox(height: 8),
76 | Text(label)
77 | ],
78 | );
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_list.dart:
--------------------------------------------------------------------------------
1 | // TODO(mono): ちょっと面倒で未実装
2 | // 別サンプル: https://github.com/TaskShare/taskshare-flutter/blob/master/lib/screens/task/list/task_list.dart
3 | import 'package:animations_app/widget/app_scaffold.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimatedListPage extends StatefulWidget {
7 | const AnimatedListPage({super.key});
8 |
9 | static const routeName = 'AnimatedList';
10 |
11 | @override
12 | State createState() => _AnimatedListPageState();
13 | }
14 |
15 | class _AnimatedListPageState extends State {
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'AnimatedList(WIP)',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {},
22 | child: const Icon(Icons.refresh),
23 | ),
24 | child: Container(),
25 | );
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_modal_barrier.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedModalBarrierPage extends StatefulWidget {
5 | const AnimatedModalBarrierPage({super.key});
6 |
7 | static const routeName = 'AnimatedModalBarrier';
8 |
9 | @override
10 | State createState() {
11 | return _AnimatedModalBarrierPageState();
12 | }
13 | }
14 |
15 | class _AnimatedModalBarrierPageState extends State {
16 | var _dismissible = false;
17 | @override
18 | Widget build(BuildContext context) {
19 | return AppScaffold(
20 | title: 'AnimatedModalBarrier',
21 | child: Center(
22 | child: Column(
23 | mainAxisAlignment: MainAxisAlignment.center,
24 | children: [
25 | ElevatedButton(
26 | onPressed: () {
27 | Navigator.of(context).push(
28 | MyPageRoute(
29 | page: _ModalPage(),
30 | dismissible: _dismissible,
31 | ),
32 | );
33 | },
34 | child: const Text('Open Modal View'),
35 | ),
36 | Row(
37 | mainAxisAlignment: MainAxisAlignment.center,
38 | children: [
39 | const Text('dismissible'),
40 | Switch(
41 | onChanged: (value) {
42 | setState(() {
43 | _dismissible = value;
44 | });
45 | },
46 | value: _dismissible,
47 | ),
48 | ],
49 | ),
50 | ],
51 | ),
52 | ),
53 | );
54 | }
55 | }
56 |
57 | class MyPageRoute extends TransitionRoute {
58 | MyPageRoute({
59 | required this.page,
60 | required this.dismissible,
61 | });
62 |
63 | final Widget page;
64 | final bool dismissible;
65 |
66 | @override
67 | Iterable createOverlayEntries() {
68 | return [
69 | OverlayEntry(builder: _buildModalBarrier),
70 | OverlayEntry(builder: (context) => Center(child: page))
71 | ];
72 | }
73 |
74 | @override
75 | bool get opaque => false;
76 |
77 | @override
78 | Duration get transitionDuration => const Duration(milliseconds: 500);
79 |
80 | Widget _buildModalBarrier(BuildContext context) {
81 | final animation = this.animation!;
82 | return IgnorePointer(
83 | // changedInternalState is called when this updates
84 | ignoring: animation.status == AnimationStatus.reverse ||
85 | // dismissed is possible when doing a manual pop gesture
86 | animation.status == AnimationStatus.dismissed,
87 | child: AnimatedModalBarrier(
88 | color: animation.drive(
89 | ColorTween(
90 | begin: Colors.transparent,
91 | end: Colors.black.withAlpha(80),
92 | ),
93 | ),
94 | dismissible: dismissible,
95 | ),
96 | );
97 | }
98 | }
99 |
100 | class _ModalPage extends StatelessWidget {
101 | @override
102 | Widget build(BuildContext context) {
103 | return Card(
104 | child: Padding(
105 | padding: const EdgeInsets.all(16),
106 | child: Column(
107 | mainAxisSize: MainAxisSize.min,
108 | children: [
109 | const Text('( ´・‿・`)'),
110 | const SizedBox(height: 8),
111 | ElevatedButton(
112 | onPressed: () {
113 | Navigator.of(context).pop();
114 | },
115 | child: const Text('Close'),
116 | )
117 | ],
118 | ),
119 | ),
120 | );
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_opacity.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedOpacityPage extends StatefulWidget {
5 | const AnimatedOpacityPage({super.key});
6 |
7 | static const routeName = 'animatedOpacity';
8 |
9 | @override
10 | State createState() => _AnimatedOpacityPageState();
11 | }
12 |
13 | class _AnimatedOpacityPageState extends State {
14 | var _opaque = true;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'AnimatedOpacity',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {
22 | setState(() {
23 | _opaque = !_opaque;
24 | });
25 | },
26 | child: const Icon(Icons.refresh),
27 | ),
28 | child: Center(
29 | child: AnimatedOpacity(
30 | duration: const Duration(milliseconds: 500),
31 | opacity: _opaque ? 1 : 0.3,
32 | child: Image.asset('assets/love.png'),
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_padding.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedPaddingPage extends StatefulWidget {
5 | const AnimatedPaddingPage({super.key});
6 |
7 | static const routeName = 'animatedPadding';
8 |
9 | @override
10 | State createState() => _AnimatedPaddingPageState();
11 | }
12 |
13 | class _AnimatedPaddingPageState extends State {
14 | var _hasPadding = false;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'AnimatedPadding',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {
22 | setState(() {
23 | _hasPadding = !_hasPadding;
24 | });
25 | },
26 | child: const Icon(Icons.refresh),
27 | ),
28 | child: Center(
29 | child: AnimatedPadding(
30 | duration: const Duration(milliseconds: 500),
31 | padding: EdgeInsets.all(_hasPadding ? 64 : 0),
32 | child: Image.asset('assets/love.png'),
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_physical_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedPhysicalModelPage extends StatefulWidget {
5 | const AnimatedPhysicalModelPage({super.key});
6 |
7 | static const routeName = 'animatedPhysicalModel';
8 |
9 | @override
10 | State createState() =>
11 | _AnimatedPhysicalModelPageState();
12 | }
13 |
14 | class _AnimatedPhysicalModelPageState extends State {
15 | var _hasElevation = false;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return AppScaffold(
20 | title: 'AnimatedPhysicalModel',
21 | floatingActionButton: FloatingActionButton(
22 | onPressed: () {
23 | setState(() {
24 | _hasElevation = !_hasElevation;
25 | });
26 | },
27 | child: const Icon(Icons.refresh),
28 | ),
29 | child: Center(
30 | child: Padding(
31 | padding: const EdgeInsets.all(32),
32 | child: AnimatedPhysicalModel(
33 | color: Colors.purple,
34 | shadowColor: Colors.black,
35 | shape: BoxShape.rectangle,
36 | duration: const Duration(milliseconds: 500),
37 | elevation: _hasElevation ? 16 : 0,
38 | child: Padding(
39 | padding: const EdgeInsets.all(8),
40 | child: Image.asset('assets/love.png'),
41 | ),
42 | ),
43 | ),
44 | ),
45 | );
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_positioned.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedPositionedPage extends StatefulWidget {
5 | const AnimatedPositionedPage({super.key});
6 |
7 | static const routeName = 'animatedPositioned';
8 |
9 | @override
10 | State createState() => _AnimatedPositionedPageState();
11 | }
12 |
13 | class _AnimatedPositionedPageState extends State {
14 | var _shrinked = true;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'AnimatedPositioned',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {
22 | setState(() {
23 | _shrinked = !_shrinked;
24 | });
25 | },
26 | child: const Icon(Icons.refresh),
27 | ),
28 | child: Center(
29 | child: Stack(
30 | children: [
31 | Image.asset('assets/love_gray.png'),
32 | // nullと数値指定の変化のアニメーションには非対応なので注意
33 | AnimatedPositioned(
34 | top: 0,
35 | left: 0,
36 | width: _shrinked ? 50 : 300,
37 | duration: const Duration(milliseconds: 500),
38 | curve: Curves.easeInOut,
39 | child: Image.asset('assets/love.png'),
40 | ),
41 | ],
42 | ),
43 | ),
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_positioned_directional.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedPositionedDirectionalPage extends StatefulWidget {
5 | const AnimatedPositionedDirectionalPage({super.key});
6 |
7 | static const routeName = 'animatedPositionedDirectional';
8 |
9 | @override
10 | State createState() =>
11 | _AnimatedPositionedDirectionalPageState();
12 | }
13 |
14 | class _AnimatedPositionedDirectionalPageState
15 | extends State {
16 | var _shrinked = true;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return AppScaffold(
21 | title: 'AnimatedPositionedDirectional',
22 | floatingActionButton: FloatingActionButton(
23 | onPressed: () {
24 | setState(() {
25 | _shrinked = !_shrinked;
26 | });
27 | },
28 | child: const Icon(Icons.refresh),
29 | ),
30 | child: Center(
31 | child: Stack(
32 | children: [
33 | Image.asset('assets/love_gray.png'),
34 | // nullと数値指定の変化のアニメーションには非対応なので注意
35 | Directionality(
36 | textDirection: TextDirection.rtl,
37 | child: AnimatedPositionedDirectional(
38 | top: 0,
39 | start: 0,
40 | width: _shrinked ? 50 : 300,
41 | duration: const Duration(milliseconds: 500),
42 | curve: Curves.easeInOut,
43 | child: Image.asset('assets/love.png'),
44 | ),
45 | ),
46 | ],
47 | ),
48 | ),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_size_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // MEMO: ImplicitlyAnimatedWidgetの派生クラスではない
5 | /// See: https://medium.com/flutter-community/flutter-working-with-animatedsize-35253ff8f16a
6 | class AnimatedSizePage extends StatefulWidget {
7 | const AnimatedSizePage({super.key});
8 |
9 | static const routeName = 'animatedSize';
10 |
11 | @override
12 | State createState() => _AnimatedSizePageState();
13 | }
14 |
15 | class _AnimatedSizePageState extends State {
16 | var _isSmall = true;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return AppScaffold(
21 | title: 'AnimatedSize',
22 | floatingActionButton: FloatingActionButton(
23 | onPressed: () {
24 | setState(() {
25 | _isSmall = !_isSmall;
26 | });
27 | },
28 | child: const Icon(Icons.refresh),
29 | ),
30 | child: Center(
31 | child: AnimatedSize(
32 | duration: const Duration(milliseconds: 500),
33 | child: SizedBox(
34 | width: _isSmall ? 100 : 200,
35 | height: _isSmall ? 100 : 200,
36 | child: Image.asset('assets/love.png'),
37 | ),
38 | ),
39 | ),
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_switcher_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | // MEMO: ImplicitlyAnimatedWidgetの派生クラスではない
5 | /// See: https://medium.com/flutter-community/what-do-you-know-about-aniamtedswitcher-53cc3a4bebb8
6 | class AnimatedSwitcherPage extends StatefulWidget {
7 | const AnimatedSwitcherPage({super.key});
8 |
9 | static const routeName = 'animatedSwitcher';
10 |
11 | @override
12 | State createState() => _AnimatedSwitcherPageState();
13 | }
14 |
15 | class _AnimatedSwitcherPageState extends State {
16 | var _isDefaultImage = true;
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return AppScaffold(
21 | title: 'AnimatedSwitcher',
22 | floatingActionButton: FloatingActionButton(
23 | onPressed: () {
24 | setState(() {
25 | _isDefaultImage = !_isDefaultImage;
26 | });
27 | },
28 | child: const Icon(Icons.refresh),
29 | ),
30 | child: Center(
31 | child: AnimatedSwitcher(
32 | duration: const Duration(milliseconds: 500),
33 | child: Image.asset(
34 | 'assets/love${_isDefaultImage ? '' : '_gray'}.png',
35 | key: UniqueKey(),
36 | ),
37 | ),
38 | ),
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/animated_theme_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class AnimatedThemePage extends StatefulWidget {
5 | const AnimatedThemePage({super.key});
6 |
7 | static const routeName = 'animatedTheme';
8 |
9 | @override
10 | State createState() => _AnimatedThemePageState();
11 | }
12 |
13 | class _AnimatedThemePageState extends State {
14 | var _isLightTheme = true;
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'AnimatedTheme',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {
22 | setState(() {
23 | _isLightTheme = !_isLightTheme;
24 | });
25 | },
26 | child: const Icon(Icons.refresh),
27 | ),
28 | child: Center(
29 | child: AnimatedTheme(
30 | data: _isLightTheme ? ThemeData.light() : ThemeData.dark(),
31 | duration: const Duration(milliseconds: 500),
32 | child: const Card(
33 | child: Padding(
34 | padding: EdgeInsets.all(16),
35 | child: Text(
36 | 'hello',
37 | style: TextStyle(fontSize: 24),
38 | ),
39 | ),
40 | ),
41 | ),
42 | ),
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/fade_in_image_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/app_scaffold.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:transparent_image/transparent_image.dart';
4 |
5 | class FadeInImagePage extends StatefulWidget {
6 | const FadeInImagePage({super.key});
7 |
8 | static const routeName = 'FadeInImage';
9 |
10 | @override
11 | State createState() => _FadeInImagePageState();
12 | }
13 |
14 | class _FadeInImagePageState extends State {
15 | var _index = 0;
16 | @override
17 | Widget build(BuildContext context) {
18 | return AppScaffold(
19 | title: 'FadeInImage',
20 | floatingActionButton: FloatingActionButton(
21 | onPressed: () {
22 | setState(() => _index++);
23 | },
24 | child: const Icon(Icons.refresh),
25 | ),
26 | child: _index.isEven
27 | ? Stack(
28 | children: [
29 | const Center(child: CircularProgressIndicator()),
30 | Center(
31 | child: FadeInImage.memoryNetwork(
32 | placeholder: kTransparentImage,
33 | image: 'https://picsum.photos/400?image=$_index',
34 | fadeInCurve: Curves.easeInOut,
35 | ),
36 | /*
37 | child: FadeInImage.assetNetwork(
38 | placeholder: 'assets/love_gray.png',
39 | image: 'https://picsum.photos/400?image=$index',
40 | fadeInCurve: Curves.easeInOut,
41 | ),
42 | */
43 | ),
44 | ],
45 | )
46 | : const Center(
47 | child: Text('Press button one more.'),
48 | ),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/hero_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/widget/widget.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | const _heroTagImage = 'image';
5 | const _heroTagText = 'text';
6 | final _image = Image.asset('assets/love.png');
7 | const _text = 'I am a dog 🐶';
8 |
9 | class HeroPage extends StatelessWidget {
10 | const HeroPage({super.key});
11 |
12 | static const routeName = 'Hero';
13 | @override
14 | Widget build(BuildContext context) {
15 | return AppScaffold(
16 | title: 'Hero',
17 | child: InkWell(
18 | onTap: () => Navigator.of(context).push(
19 | MaterialPageRoute(builder: (context) => const DetailScreen()),
20 | ),
21 | child: SizedBox(
22 | height: 60,
23 | child: Row(
24 | children: [
25 | Hero(
26 | tag: _heroTagImage,
27 | child: _image,
28 | ),
29 | const SizedBox(width: 16),
30 | const Hero(
31 | tag: _heroTagText,
32 | child: Material(
33 | color: Colors.transparent,
34 | child: Text(_text),
35 | ),
36 | ),
37 | ],
38 | ),
39 | ),
40 | ),
41 | );
42 | }
43 | }
44 |
45 | class DetailScreen extends StatelessWidget {
46 | const DetailScreen({super.key});
47 |
48 | @override
49 | Widget build(BuildContext context) {
50 | return AppScaffold(
51 | title: 'Detail',
52 | child: Column(
53 | children: [
54 | Hero(
55 | tag: _heroTagImage,
56 | child: _image,
57 | ),
58 | const SizedBox(height: 16),
59 | const Hero(
60 | tag: _heroTagText,
61 | child: Material(
62 | color: Colors.transparent,
63 | child: Text(
64 | _text,
65 | style: TextStyle(fontSize: 32),
66 | ),
67 | ),
68 | ),
69 | ],
70 | ),
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/pages/implicitly_animated/implicitly_animated_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/implicitly_animated/animated_align.dart';
2 | import 'package:animations_app/pages/implicitly_animated/animated_container.dart';
3 | import 'package:animations_app/pages/implicitly_animated/animated_cross_fade.dart';
4 | import 'package:animations_app/pages/implicitly_animated/animated_default_text_style.dart';
5 | import 'package:animations_app/pages/implicitly_animated/animated_icon.dart';
6 | import 'package:animations_app/pages/implicitly_animated/animated_list.dart';
7 | import 'package:animations_app/pages/implicitly_animated/animated_modal_barrier.dart';
8 | import 'package:animations_app/pages/implicitly_animated/animated_opacity.dart';
9 | import 'package:animations_app/pages/implicitly_animated/animated_padding.dart';
10 | import 'package:animations_app/pages/implicitly_animated/animated_physical_model.dart';
11 | import 'package:animations_app/pages/implicitly_animated/animated_positioned.dart';
12 | import 'package:animations_app/pages/implicitly_animated/animated_positioned_directional.dart';
13 | import 'package:animations_app/pages/implicitly_animated/animated_size_page.dart';
14 | import 'package:animations_app/pages/implicitly_animated/animated_switcher_page.dart';
15 | import 'package:animations_app/pages/implicitly_animated/animated_theme_page.dart';
16 | import 'package:animations_app/pages/implicitly_animated/fade_in_image_page.dart';
17 | import 'package:animations_app/pages/implicitly_animated/hero_page.dart';
18 | import 'package:animations_app/widget/app_list_tile.dart';
19 | import 'package:animations_app/widget/app_scaffold.dart';
20 | import 'package:flutter/material.dart';
21 |
22 | /// Examples of [ImplicitlyAnimatedWidget]
23 | class ImplicitlyAnimatedPage extends StatelessWidget {
24 | const ImplicitlyAnimatedPage({super.key});
25 |
26 | static const routeName = 'implicitlyAnimated';
27 | @override
28 | Widget build(BuildContext context) {
29 | return AppScaffold(
30 | title: 'Animated',
31 | child: ListView(
32 | children: const [
33 | AppListTile(
34 | title: 'AnimatedAlign',
35 | nextRouteName: AnimatedAlignPage.routeName,
36 | ),
37 | AppListTile(
38 | title: 'AnimatedContainer',
39 | nextRouteName: AnimatedContainerPage.routeName,
40 | ),
41 | AppListTile(
42 | title: 'AnimatedCrossFade',
43 | nextRouteName: AnimatedCrossFadePage.routeName,
44 | ),
45 | AppListTile(
46 | title: 'AnimatedDefaultTextStyle',
47 | nextRouteName: AnimatedDefaultTextStylePage.routeName,
48 | ),
49 | AppListTile(
50 | title: 'AnimatedIcon',
51 | nextRouteName: AnimatedIconPage.routeName,
52 | ),
53 | AppListTile(
54 | title: 'AnimatedList',
55 | nextRouteName: AnimatedListPage.routeName,
56 | ),
57 | AppListTile(
58 | title: 'AnimatedModalBarrier',
59 | nextRouteName: AnimatedModalBarrierPage.routeName,
60 | ),
61 | AppListTile(
62 | title: 'AnimatedOpacity',
63 | nextRouteName: AnimatedOpacityPage.routeName,
64 | ),
65 | AppListTile(
66 | title: 'AnimatedPadding',
67 | nextRouteName: AnimatedPaddingPage.routeName,
68 | ),
69 | AppListTile(
70 | title: 'AnimatedPhysicalModel',
71 | nextRouteName: AnimatedPhysicalModelPage.routeName,
72 | ),
73 | AppListTile(
74 | title: 'AnimatedPositioned',
75 | nextRouteName: AnimatedPositionedPage.routeName,
76 | ),
77 | AppListTile(
78 | title: 'AnimatedPositionedDirectional',
79 | nextRouteName: AnimatedPositionedDirectionalPage.routeName,
80 | ),
81 | AppListTile(
82 | title: 'AnimatedTheme',
83 | nextRouteName: AnimatedThemePage.routeName,
84 | ),
85 | AppListTile(
86 | title: 'AnimatedSwitcher',
87 | nextRouteName: AnimatedSwitcherPage.routeName,
88 | ),
89 | AppListTile(
90 | title: 'AnimatedSize',
91 | nextRouteName: AnimatedSizePage.routeName,
92 | ),
93 | AppListTile(
94 | title: 'Hero',
95 | nextRouteName: HeroPage.routeName,
96 | ),
97 | AppListTile(
98 | title: 'FadeInImage',
99 | nextRouteName: FadeInImagePage.routeName,
100 | ),
101 | ],
102 | ),
103 | );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/lib/pages/transition/align_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class AlignTransitionPage extends StatefulWidget {
6 | const AlignTransitionPage({super.key});
7 |
8 | static const routeName = 'AlignTransition';
9 |
10 | @override
11 | State createState() => _AlignTransitionPageState();
12 | }
13 |
14 | class _AlignTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 | var _isMoved = false;
21 |
22 | @override
23 | void dispose() {
24 | _animationController.dispose();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return AppScaffold(
31 | title: 'AlignTransition',
32 | floatingActionButton: FloatingActionButton(
33 | onPressed: () {
34 | if (_isMoved) {
35 | _animationController.reverse();
36 | } else {
37 | _animationController.forward();
38 | }
39 | _isMoved = !_isMoved;
40 | },
41 | child: const Icon(Icons.refresh),
42 | ),
43 | child: Stack(
44 | children: [
45 | AlignTransition(
46 | alignment: _animationController
47 | .drive(
48 | CurveTween(
49 | curve: const Interval(0.4, 1, curve: Curves.fastOutSlowIn),
50 | ),
51 | )
52 | .drive(
53 | AlignmentTween(
54 | begin: Alignment.topLeft,
55 | end: Alignment.bottomRight,
56 | ),
57 | ),
58 | child: Image.asset(
59 | 'assets/love_gray.png',
60 | width: 200,
61 | ),
62 | ),
63 | AlignTransition(
64 | alignment: _animationController
65 | .drive(
66 | CurveTween(
67 | curve: const Interval(0, 0.6, curve: Curves.fastOutSlowIn),
68 | ),
69 | )
70 | .drive(
71 | AlignmentTween(
72 | begin: Alignment.topLeft,
73 | end: Alignment.bottomRight,
74 | ),
75 | ),
76 | child: Image.asset(
77 | 'assets/love.png',
78 | width: 200,
79 | ),
80 | ),
81 | ],
82 | ),
83 | );
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/pages/transition/decorated_box_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class DecoratedBoxTransitionPage extends StatefulWidget {
6 | const DecoratedBoxTransitionPage({super.key});
7 |
8 | static const routeName = 'DecoratedBoxTransition';
9 |
10 | @override
11 | State createState() =>
12 | _DecoratedBoxTransitionPageState();
13 | }
14 |
15 | class _DecoratedBoxTransitionPageState extends State
16 | with SingleTickerProviderStateMixin {
17 | late final AnimationController _animationController = AnimationController(
18 | vsync: this,
19 | duration: const Duration(milliseconds: 500),
20 | );
21 | var _isScaledUp = false;
22 |
23 | @override
24 | void dispose() {
25 | _animationController.dispose();
26 | super.dispose();
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return AppScaffold(
32 | title: 'DecoratedBoxTransition',
33 | floatingActionButton: FloatingActionButton(
34 | onPressed: () {
35 | if (_isScaledUp) {
36 | _animationController.reverse();
37 | } else {
38 | _animationController.forward();
39 | }
40 | _isScaledUp = !_isScaledUp;
41 | },
42 | child: const Icon(Icons.refresh),
43 | ),
44 | child: Center(
45 | child: DecoratedBoxTransition(
46 | decoration: _animationController
47 | .drive(
48 | CurveTween(curve: Curves.fastOutSlowIn),
49 | )
50 | .drive(
51 | DecorationTween(
52 | begin: const FlutterLogoDecoration(
53 | style: FlutterLogoStyle.horizontal,
54 | ),
55 | end: const FlutterLogoDecoration(
56 | style: FlutterLogoStyle.stacked,
57 | ),
58 | ),
59 | ),
60 | child: const SizedBox(
61 | width: 200,
62 | height: 200,
63 | ),
64 | ),
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/pages/transition/default_text_style_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class DefaultTextStyleTransitionPage extends StatefulWidget {
6 | const DefaultTextStyleTransitionPage({super.key});
7 |
8 | static const routeName = 'DefaultTextStyleTransition';
9 |
10 | @override
11 | State createState() =>
12 | _DefaultTextStyleTransitionPageState();
13 | }
14 |
15 | class _DefaultTextStyleTransitionPageState
16 | extends State
17 | with SingleTickerProviderStateMixin {
18 | late final AnimationController _animationController = AnimationController(
19 | vsync: this,
20 | duration: const Duration(milliseconds: 500),
21 | );
22 | var _isScaledUp = false;
23 |
24 | @override
25 | void dispose() {
26 | _animationController.dispose();
27 | super.dispose();
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return AppScaffold(
33 | title: 'DefaultTextStyleTransition',
34 | floatingActionButton: FloatingActionButton(
35 | onPressed: () {
36 | if (_isScaledUp) {
37 | _animationController.reverse();
38 | } else {
39 | _animationController.forward();
40 | }
41 | _isScaledUp = !_isScaledUp;
42 | },
43 | child: const Icon(Icons.refresh),
44 | ),
45 | child: DefaultTextStyleTransition(
46 | style: _animationController
47 | .drive(
48 | CurveTween(curve: Curves.fastOutSlowIn),
49 | )
50 | .drive(
51 | TextStyleTween(
52 | begin: Theme.of(context).textTheme.headline4,
53 | end: Theme.of(context).textTheme.headline1,
54 | ),
55 | ),
56 | child: const Center(child: Text('Flutter')),
57 | ),
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/pages/transition/fade_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class FadeTransitionPage extends StatefulWidget {
6 | const FadeTransitionPage({super.key});
7 |
8 | static const routeName = 'FadeTransition';
9 |
10 | @override
11 | State createState() => _FadeTransitionPageState();
12 | }
13 |
14 | class _FadeTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 | var _isScaledUp = false;
21 |
22 | @override
23 | void dispose() {
24 | _animationController.dispose();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | final height = MediaQuery.of(context).size.width / 2;
31 | return AppScaffold(
32 | title: 'FadeTransition',
33 | floatingActionButton: FloatingActionButton(
34 | onPressed: () {
35 | if (_isScaledUp) {
36 | _animationController.reverse();
37 | } else {
38 | _animationController.forward();
39 | }
40 | _isScaledUp = !_isScaledUp;
41 | },
42 | child: const Icon(Icons.refresh),
43 | ),
44 | child: Column(
45 | children: [
46 | SizedBox(
47 | height: height,
48 | child: Row(
49 | children: [
50 | _buildContent(0),
51 | _buildContent(0.2),
52 | ],
53 | ),
54 | ),
55 | SizedBox(
56 | height: height,
57 | child: Row(
58 | children: [
59 | _buildContent(0.4),
60 | _buildContent(0.6),
61 | ],
62 | ),
63 | ),
64 | ],
65 | ),
66 | );
67 | }
68 |
69 | FadeTransition _buildContent(double start) {
70 | return FadeTransition(
71 | opacity: _animationController
72 | .drive(
73 | CurveTween(
74 | curve: Interval(
75 | start,
76 | start + 0.4,
77 | curve: Curves.fastOutSlowIn,
78 | ),
79 | ),
80 | )
81 | .drive(
82 | Tween(
83 | begin: 0.1,
84 | end: 1,
85 | ),
86 | ),
87 | child: Image.asset('assets/love.png'),
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/pages/transition/positioned_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class PositionedTransitionPage extends StatefulWidget {
6 | const PositionedTransitionPage({super.key});
7 |
8 | static const routeName = 'PositionedTransition';
9 |
10 | @override
11 | State createState() =>
12 | _PositionedTransitionPageState();
13 | }
14 |
15 | class _PositionedTransitionPageState extends State
16 | with SingleTickerProviderStateMixin {
17 | late final AnimationController _animationController = AnimationController(
18 | vsync: this,
19 | duration: const Duration(milliseconds: 3000),
20 | );
21 | var _isMoved = false;
22 |
23 | @override
24 | void dispose() {
25 | _animationController.dispose();
26 | super.dispose();
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return AppScaffold(
32 | title: 'PositionedTransition',
33 | floatingActionButton: FloatingActionButton(
34 | onPressed: () {
35 | if (_isMoved) {
36 | _animationController.reverse();
37 | } else {
38 | _animationController.forward();
39 | }
40 | _isMoved = !_isMoved;
41 | },
42 | child: const Icon(Icons.refresh),
43 | ),
44 | child: Stack(
45 | children: [
46 | PositionedTransition(
47 | rect: _animationController
48 | .drive(
49 | CurveTween(
50 | curve: Curves.elasticInOut,
51 | ),
52 | )
53 | .drive(
54 | RelativeRectTween(
55 | begin: const RelativeRect.fromLTRB(10, 10, 200, 400),
56 | end: const RelativeRect.fromLTRB(100, 400, 10, 10),
57 | ),
58 | ),
59 | child: Image.asset(
60 | 'assets/love.png',
61 | fit: BoxFit.cover,
62 | ),
63 | )
64 | ],
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/pages/transition/relative_positioned_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class RelativePositionedTransitionPage extends StatefulWidget {
6 | const RelativePositionedTransitionPage({super.key});
7 |
8 | static const routeName = 'RelativePositionedTransition';
9 |
10 | @override
11 | State createState() =>
12 | _RelativePositionedTransitionPageState();
13 | }
14 |
15 | class _RelativePositionedTransitionPageState
16 | extends State
17 | with SingleTickerProviderStateMixin {
18 | late final AnimationController _animationController = AnimationController(
19 | vsync: this,
20 | duration: const Duration(milliseconds: 3000),
21 | );
22 | var _isMoved = false;
23 |
24 | @override
25 | void dispose() {
26 | _animationController.dispose();
27 | super.dispose();
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | return AppScaffold(
33 | title: 'RelativePositionedTransition',
34 | floatingActionButton: FloatingActionButton(
35 | onPressed: () {
36 | if (_isMoved) {
37 | _animationController.reverse();
38 | } else {
39 | _animationController.forward();
40 | }
41 | _isMoved = !_isMoved;
42 | },
43 | child: const Icon(Icons.refresh),
44 | ),
45 | child: Stack(
46 | children: [
47 | RelativePositionedTransition(
48 | rect: _animationController
49 | .drive(
50 | CurveTween(
51 | curve: Curves.elasticInOut,
52 | ),
53 | )
54 | .drive(
55 | RectTween(
56 | begin: const Rect.fromLTRB(10, 10, -100, -400),
57 | end: const Rect.fromLTRB(200, 500, 0, 0),
58 | ),
59 | ),
60 | size: const Size(50, 50),
61 | child: Image.asset(
62 | 'assets/love.png',
63 | fit: BoxFit.cover,
64 | ),
65 | )
66 | ],
67 | ),
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/pages/transition/rotation_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class RotationTransitionPage extends StatefulWidget {
6 | const RotationTransitionPage({super.key});
7 |
8 | static const routeName = 'RotationTransition';
9 |
10 | @override
11 | State createState() => _RotationTransitionPageState();
12 | }
13 |
14 | class _RotationTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 3000),
19 | );
20 |
21 | @override
22 | void dispose() {
23 | _animationController.dispose();
24 | super.dispose();
25 | }
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return AppScaffold(
30 | title: 'RotationTransition',
31 | floatingActionButton: FloatingActionButton(
32 | onPressed: () {
33 | _animationController.forward(from: 0);
34 | },
35 | child: const Icon(Icons.refresh),
36 | ),
37 | child: RotationTransition(
38 | alignment: Alignment.bottomCenter,
39 | turns: _animationController
40 | .drive(
41 | CurveTween(
42 | curve: Curves.elasticOut,
43 | ),
44 | )
45 | .drive(
46 | Tween(
47 | begin: 0,
48 | end: 1,
49 | ),
50 | ),
51 | child: Image.asset('assets/love.png'),
52 | ),
53 | );
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/pages/transition/scale_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class ScaleTransitionPage extends StatefulWidget {
6 | const ScaleTransitionPage({super.key});
7 |
8 | static const routeName = 'ScaleTransition';
9 |
10 | @override
11 | State createState() => _ScaleTransitionPageState();
12 | }
13 |
14 | class _ScaleTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 | var _isScaledUp = false;
21 |
22 | @override
23 | void dispose() {
24 | _animationController.dispose();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return AppScaffold(
31 | title: 'ScaleTransition',
32 | floatingActionButton: FloatingActionButton(
33 | onPressed: () {
34 | if (_isScaledUp) {
35 | _animationController.reverse();
36 | } else {
37 | _animationController.forward();
38 | }
39 | _isScaledUp = !_isScaledUp;
40 | },
41 | child: const Icon(Icons.refresh),
42 | ),
43 | child: Column(
44 | children: [
45 | ScaleTransition(
46 | alignment: Alignment.bottomCenter,
47 | scale: _animationController
48 | .drive(
49 | CurveTween(
50 | curve: const Interval(0, 0.8, curve: Curves.fastOutSlowIn),
51 | ),
52 | )
53 | .drive(
54 | Tween(
55 | begin: 0.3,
56 | end: 1,
57 | ),
58 | ),
59 | child: Image.asset('assets/love.png'),
60 | ),
61 | const SizedBox(height: 16),
62 | ScaleTransition(
63 | alignment: Alignment.topCenter,
64 | scale: _animationController
65 | .drive(
66 | CurveTween(
67 | curve: const Interval(0.4, 1, curve: Curves.fastOutSlowIn),
68 | ),
69 | )
70 | .drive(
71 | Tween(
72 | begin: 0.3,
73 | end: 1,
74 | ),
75 | ),
76 | child: const Text(
77 | 'I am a dog 🐶',
78 | style: TextStyle(fontSize: 32),
79 | ),
80 | )
81 | ],
82 | ),
83 | );
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/lib/pages/transition/size_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class SizeTransitionPage extends StatefulWidget {
6 | const SizeTransitionPage({super.key});
7 |
8 | static const routeName = 'SizeTransition';
9 |
10 | @override
11 | State createState() => _SizeTransitionPageState();
12 | }
13 |
14 | class _SizeTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 | var _isScaledUp = false;
21 |
22 | @override
23 | void dispose() {
24 | _animationController.dispose();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return AppScaffold(
31 | title: 'SizeTransition',
32 | floatingActionButton: FloatingActionButton(
33 | onPressed: () {
34 | if (_isScaledUp) {
35 | _animationController.reverse();
36 | } else {
37 | _animationController.forward();
38 | }
39 | _isScaledUp = !_isScaledUp;
40 | },
41 | child: const Icon(Icons.refresh),
42 | ),
43 | child: SizeTransition(
44 | axisAlignment: -0.3,
45 | sizeFactor: _animationController
46 | .drive(
47 | CurveTween(curve: Curves.fastOutSlowIn),
48 | )
49 | .drive(
50 | Tween(
51 | begin: 0.2,
52 | end: 1,
53 | ),
54 | ),
55 | child: Image.asset('assets/love.png'),
56 | ),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/pages/transition/slide_transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../widget/app_scaffold.dart';
4 |
5 | class SlideTransitionPage extends StatefulWidget {
6 | const SlideTransitionPage({super.key});
7 |
8 | static const routeName = 'slideTransition';
9 |
10 | @override
11 | State createState() => _SlideTransitionPageState();
12 | }
13 |
14 | class _SlideTransitionPageState extends State
15 | with SingleTickerProviderStateMixin {
16 | late final AnimationController _animationController = AnimationController(
17 | vsync: this,
18 | duration: const Duration(milliseconds: 500),
19 | );
20 |
21 | @override
22 | void dispose() {
23 | _animationController.dispose();
24 | super.dispose();
25 | }
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return AppScaffold(
30 | title: 'SlideTransition',
31 | child: Stack(
32 | children: [
33 | _buildContent(),
34 | SlideTransition(
35 | position: _animationController
36 | .drive(CurveTween(curve: Curves.easeInOut))
37 | .drive(
38 | Tween(
39 | begin: Offset.zero,
40 | end: const Offset(0, -1),
41 | ),
42 | ),
43 | child: _buildTransitionScreen(),
44 | ),
45 | ],
46 | ),
47 | );
48 | }
49 |
50 | Column _buildContent() {
51 | return Column(
52 | mainAxisAlignment: MainAxisAlignment.center,
53 | children: [
54 | Image.asset('assets/love.png'),
55 | ElevatedButton(
56 | onPressed: _animationController.reverse,
57 | child: const Text('CLOSE'),
58 | )
59 | ],
60 | );
61 | }
62 |
63 | Widget _buildTransitionScreen() {
64 | return SizedBox.expand(
65 | child: ColoredBox(
66 | color: Colors.black,
67 | child: Center(
68 | child: ElevatedButton(
69 | onPressed: _animationController.forward,
70 | child: const Text('OPEN'),
71 | ),
72 | ),
73 | ),
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/pages/transition/transition_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:animations_app/pages/transition/align_transition_page.dart';
2 | import 'package:animations_app/pages/transition/decorated_box_transition_page.dart';
3 | import 'package:animations_app/pages/transition/default_text_style_transition_page.dart';
4 | import 'package:animations_app/pages/transition/fade_transition_page.dart';
5 | import 'package:animations_app/pages/transition/positioned_transition_page.dart';
6 | import 'package:animations_app/pages/transition/relative_positioned_transition_page.dart';
7 | import 'package:animations_app/pages/transition/rotation_transition_page.dart';
8 | import 'package:animations_app/pages/transition/scale_transition_page.dart';
9 | import 'package:animations_app/pages/transition/size_transition_page.dart';
10 | import 'package:animations_app/pages/transition/slide_transition_page.dart';
11 | import 'package:animations_app/widget/app_list_tile.dart';
12 | import 'package:animations_app/widget/app_scaffold.dart';
13 | import 'package:flutter/material.dart';
14 |
15 | /// Examples of [TransitionPage]
16 | class TransitionPage extends StatelessWidget {
17 | const TransitionPage({super.key});
18 |
19 | static const routeName = 'TransitionPage';
20 | @override
21 | Widget build(BuildContext context) {
22 | return AppScaffold(
23 | title: 'TransitionPage',
24 | child: ListView(
25 | children: const [
26 | AppListTile(
27 | title: 'AlignTransition',
28 | nextRouteName: AlignTransitionPage.routeName,
29 | ),
30 | AppListTile(
31 | title: 'DecoratedBoxTransition',
32 | nextRouteName: DecoratedBoxTransitionPage.routeName,
33 | ),
34 | AppListTile(
35 | title: 'DefaultTextStyleTransition',
36 | nextRouteName: DefaultTextStyleTransitionPage.routeName,
37 | ),
38 | AppListTile(
39 | title: 'FadeTransition',
40 | nextRouteName: FadeTransitionPage.routeName,
41 | ),
42 | AppListTile(
43 | title: 'PositionedTransition',
44 | nextRouteName: PositionedTransitionPage.routeName,
45 | ),
46 | AppListTile(
47 | title: 'RelativePositionedTransition',
48 | nextRouteName: RelativePositionedTransitionPage.routeName,
49 | ),
50 | AppListTile(
51 | title: 'RotationTransition',
52 | nextRouteName: RotationTransitionPage.routeName,
53 | ),
54 | AppListTile(
55 | title: 'ScaleTransition',
56 | nextRouteName: ScaleTransitionPage.routeName,
57 | ),
58 | AppListTile(
59 | title: 'SizeTransition',
60 | nextRouteName: SizeTransitionPage.routeName,
61 | ),
62 | AppListTile(
63 | title: 'SlideTransition',
64 | nextRouteName: SlideTransitionPage.routeName,
65 | ),
66 | ],
67 | ),
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/util/logger.dart:
--------------------------------------------------------------------------------
1 | import 'package:simple_logger/simple_logger.dart';
2 |
3 | final logger = SimpleLogger()
4 | ..mode = LoggerMode.print
5 | ..setLevel(
6 | Level.FINEST,
7 | includeCallerInfo: true,
8 | );
9 |
--------------------------------------------------------------------------------
/lib/util/util.dart:
--------------------------------------------------------------------------------
1 | export 'logger.dart';
2 |
--------------------------------------------------------------------------------
/lib/widget/animation_object.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:animations_app/util/util.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class AnimationObject extends StatelessWidget {
7 | const AnimationObject({super.key});
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | logger.info('build');
12 | return Stack(
13 | children: [
14 | SizedBox(
15 | width: 120,
16 | height: 120,
17 | child: Image.asset('assets/love.png'),
18 | ),
19 | Positioned(
20 | left: 0,
21 | right: 0,
22 | top: 30,
23 | child: ClipRect(
24 | child: BackdropFilter(
25 | filter: ImageFilter.blur(
26 | sigmaX: 10,
27 | sigmaY: 10,
28 | ),
29 | child: Container(
30 | height: 30,
31 | color: Colors.white.withAlpha(50),
32 | ),
33 | ),
34 | ),
35 | )
36 | ],
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/widget/app_list_tile.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppListTile extends StatelessWidget {
4 | const AppListTile({
5 | super.key,
6 | required this.title,
7 | required this.nextRouteName,
8 | });
9 |
10 | final String title;
11 | final String nextRouteName;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return ListTile(
16 | title: Text(title),
17 | onTap: () {
18 | Navigator.of(context).pushNamed(nextRouteName);
19 | },
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/widget/app_scaffold.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AppScaffold extends StatelessWidget {
4 | const AppScaffold({
5 | super.key,
6 | required this.title,
7 | required this.child,
8 | this.floatingActionButton,
9 | });
10 |
11 | final String title;
12 | final Widget child;
13 | final FloatingActionButton? floatingActionButton;
14 |
15 | @override
16 | Widget build(BuildContext context) {
17 | return Scaffold(
18 | appBar: AppBar(
19 | title: Text(title),
20 | ),
21 | body: child,
22 | floatingActionButton: floatingActionButton,
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/widget/widget.dart:
--------------------------------------------------------------------------------
1 | export 'app_scaffold.dart';
2 |
--------------------------------------------------------------------------------
/macos/.gitignore:
--------------------------------------------------------------------------------
1 | # Flutter-related
2 | **/Flutter/ephemeral/
3 | **/Pods/
4 |
5 | # Xcode-related
6 | **/xcuserdata/
7 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Flutter/Flutter-Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "ephemeral/Flutter-Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Flutter/GeneratedPluginRegistrant.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | import FlutterMacOS
6 | import Foundation
7 |
8 | import dynamic_color
9 | import macos_ui
10 | import url_launcher_macos
11 |
12 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
13 | DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin"))
14 | MacOSUiPlugin.register(with: registry.registrar(forPlugin: "MacOSUiPlugin"))
15 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
16 | }
17 |
--------------------------------------------------------------------------------
/macos/Podfile:
--------------------------------------------------------------------------------
1 | platform :osx, '10.11'
2 |
3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
5 |
6 | project 'Runner', {
7 | 'Debug' => :debug,
8 | 'Profile' => :release,
9 | 'Release' => :release,
10 | }
11 |
12 | def flutter_root
13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__)
14 | unless File.exist?(generated_xcode_build_settings_path)
15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first"
16 | end
17 |
18 | File.foreach(generated_xcode_build_settings_path) do |line|
19 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
20 | return matches[1].strip if matches
21 | end
22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\""
23 | end
24 |
25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
26 |
27 | flutter_macos_podfile_setup
28 |
29 | target 'Runner' do
30 | use_frameworks!
31 | use_modular_headers!
32 |
33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
34 | end
35 |
36 | post_install do |installer|
37 | installer.pods_project.targets.each do |target|
38 | flutter_additional_macos_build_settings(target)
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/macos/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - dynamic_color (0.0.2):
3 | - FlutterMacOS
4 | - FlutterMacOS (1.0.0)
5 | - macos_ui (0.1.0):
6 | - FlutterMacOS
7 | - url_launcher_macos (0.0.1):
8 | - FlutterMacOS
9 |
10 | DEPENDENCIES:
11 | - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
12 | - FlutterMacOS (from `Flutter/ephemeral`)
13 | - macos_ui (from `Flutter/ephemeral/.symlinks/plugins/macos_ui/macos`)
14 | - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
15 |
16 | EXTERNAL SOURCES:
17 | dynamic_color:
18 | :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
19 | FlutterMacOS:
20 | :path: Flutter/ephemeral
21 | macos_ui:
22 | :path: Flutter/ephemeral/.symlinks/plugins/macos_ui/macos
23 | url_launcher_macos:
24 | :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
25 |
26 | SPEC CHECKSUMS:
27 | dynamic_color: 394d6a888650f8534e029b27d2f8bc5c64e44008
28 | FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
29 | macos_ui: 125c911559d646194386d84c017ad6819122e2db
30 | url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
31 |
32 | PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
33 |
34 | COCOAPODS: 1.11.3
35 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
64 |
65 |
71 |
73 |
79 |
80 |
81 |
82 |
84 |
85 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/macos/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | @NSApplicationMain
5 | class AppDelegate: FlutterAppDelegate {
6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
7 | return true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "app_icon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "app_icon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "app_icon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "app_icon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "app_icon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "app_icon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "app_icon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "app_icon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "app_icon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "app_icon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png
--------------------------------------------------------------------------------
/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png
--------------------------------------------------------------------------------
/macos/Runner/Configs/AppInfo.xcconfig:
--------------------------------------------------------------------------------
1 | // Application-level settings for the Runner target.
2 | //
3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the
4 | // future. If not, the values below would default to using the project name when this becomes a
5 | // 'flutter create' template.
6 |
7 | // The application's name. By default this is also the title of the Flutter window.
8 | PRODUCT_NAME = animations
9 |
10 | // The application's bundle identifier
11 | PRODUCT_BUNDLE_IDENTIFIER = com.mono0926.animations
12 |
13 | // The copyright displayed in application information
14 | PRODUCT_COPYRIGHT = Copyright © 2021 com.mono0926. All rights reserved.
15 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Debug.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "../../Flutter/Flutter-Release.xcconfig"
2 | #include "Warnings.xcconfig"
3 |
--------------------------------------------------------------------------------
/macos/Runner/Configs/Warnings.xcconfig:
--------------------------------------------------------------------------------
1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings
2 | GCC_WARN_UNDECLARED_SELECTOR = YES
3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES
4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
6 | CLANG_WARN_PRAGMA_PACK = YES
7 | CLANG_WARN_STRICT_PROTOTYPES = YES
8 | CLANG_WARN_COMMA = YES
9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES
10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES
11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
12 | GCC_WARN_SHADOW = YES
13 | CLANG_WARN_UNREACHABLE_CODE = YES
14 |
--------------------------------------------------------------------------------
/macos/Runner/DebugProfile.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.cs.allow-jit
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/macos/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSHumanReadableCopyright
26 | $(PRODUCT_COPYRIGHT)
27 | NSMainNibFile
28 | MainMenu
29 | NSPrincipalClass
30 | NSApplication
31 |
32 |
33 |
--------------------------------------------------------------------------------
/macos/Runner/MainFlutterWindow.swift:
--------------------------------------------------------------------------------
1 | import Cocoa
2 | import FlutterMacOS
3 |
4 | class MainFlutterWindow: NSWindow {
5 | override func awakeFromNib() {
6 | let flutterViewController = FlutterViewController.init()
7 | let windowFrame = self.frame
8 | self.contentViewController = flutterViewController
9 | self.setFrame(windowFrame, display: true)
10 |
11 | RegisterGeneratedPlugins(registry: flutterViewController)
12 |
13 | super.awakeFromNib()
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/macos/Runner/Release.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: animations_app
2 | description: A new Flutter application.
3 | version: 1.1.0
4 | publish_to: none
5 | environment:
6 | sdk: '>=2.17.0 <3.0.0'
7 | dependencies:
8 | cupertino_icons: any
9 | flare_flutter: any
10 | flutter:
11 | sdk: flutter
12 | keyboard_visibility:
13 | git:
14 | url: https://github.com/spiderion/flutter_keyboard_visibility.git
15 | ref: null_safe
16 | mono_kit:
17 | quiver: any
18 | simple_logger: any
19 | transparent_image: any
20 | dev_dependencies:
21 | flutter_test:
22 | sdk: flutter
23 | pedantic_mono: any
24 | flutter:
25 | uses-material-design: true
26 | assets:
27 | - assets/
28 | fonts:
29 | - family: NothingYouCouldDo
30 | fonts:
31 | - asset: fonts/NothingYouCouldDo.ttf
32 |
--------------------------------------------------------------------------------
/res/values/strings_en.arb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/res/values/strings_en.arb
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_test/flutter_test.dart';
2 |
3 | void main() {
4 | testWidgets('Smoke test', (tester) async {});
5 | }
6 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mono0926/flutter-animations/b2a53010509e89ac0af3f17d6e91f40bdeb28410/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | animations
27 |
28 |
29 |
30 |
33 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "animations",
3 | "short_name": "animations",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------