├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .metadata
├── LICENSE
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── flutter_samples
│ │ │ │ └── MainActivity.java
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── flutter_samples
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── launch_background.xml
│ │ │ └── mario_head.png
│ │ │ ├── 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
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── albums.json
├── chango.png
└── monkey.png
├── images
├── balls
│ ├── ball1.png
│ ├── ball2.png
│ ├── ball3.png
│ └── ball4.png
├── characters
│ ├── boo.png
│ ├── broly.png
│ ├── cell.png
│ ├── frieza.png
│ ├── gohan.png
│ ├── goku.png
│ └── vegeta.png
├── credit_cards
│ ├── chip.png
│ └── chip_logo.png
├── dash_dart.png
├── dash_dart_dark.png
├── mario_logo.png
├── mesi.png
├── shoes
│ ├── 1.png
│ ├── 2.png
│ ├── 3.png
│ └── 4.png
├── twitter_flutter_bg.png
└── twitter_flutter_logo.jpg
├── ios
├── .gitignore
├── Flutter
│ ├── .last_build_id
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── Runner
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── 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
│ ├── Contents.json
│ ├── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ └── mario_head.imageset
│ │ ├── Contents.json
│ │ └── mario_head.png
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ ├── Runner-Bridging-Header.h
│ └── main.m
├── lib
├── animations
│ ├── circular_list
│ │ └── circular_list_page.dart
│ ├── custom_appbar
│ │ └── my_custom_appbar_page.dart
│ ├── custom_sliverheader
│ │ └── custom_sliver_header.dart
│ ├── foldable
│ │ └── foldable_animation.dart
│ ├── hide_my_widgets
│ │ ├── hide_my_widget.dart
│ │ └── main_hide_my_widgets.dart
│ ├── list_details
│ │ ├── character.dart
│ │ ├── detail_page.dart
│ │ └── list_page.dart
│ ├── main_animations.dart
│ ├── menu_exploration
│ │ ├── main_menu_exploration.dart
│ │ └── menu_exploration.dart
│ ├── neon_button
│ │ ├── neon_button.dart
│ │ └── neon_button_main.dart
│ ├── shrink_top_list
│ │ └── shrink_top_list_page.dart
│ ├── split_widget
│ │ ├── main_split_widget.dart
│ │ ├── split_diagonal_widget.dart
│ │ └── split_half_widget.dart
│ └── turn_on_the_light
│ │ └── turn_on_the_light.dart
├── app_clone
│ ├── album_flow
│ │ ├── album.dart
│ │ ├── album_flow_detail_page.dart
│ │ ├── album_flow_page.dart
│ │ └── album_image.dart
│ ├── android_messages
│ │ └── android_messages_page.dart
│ ├── credit_cards_concept
│ │ ├── credit_card.dart
│ │ ├── credit_card_widget.dart
│ │ ├── credit_cards_concept_detail_page.dart
│ │ └── credit_cards_concept_page.dart
│ ├── main_apps_clone.dart
│ ├── movies_concept
│ │ └── movies_concept_page.dart
│ ├── photo_concept
│ │ ├── photo_concept_page.dart
│ │ └── photo_detail_page.dart
│ ├── shoes_store
│ │ ├── shoes_store_detail_page.dart
│ │ └── shoes_store_page.dart
│ ├── sports_store
│ │ ├── sports_store_detail_page.dart
│ │ └── sports_store_page.dart
│ ├── travel_concept
│ │ ├── travel_concept_detail_page.dart
│ │ └── travel_concept_page.dart
│ └── twitter_profile
│ │ └── twitter_profile_page.dart
├── appbar_sliverappbar
│ ├── main_appbar_sliverappbar.dart
│ ├── sample1.dart
│ ├── sample2.dart
│ └── sample3.dart
├── collapsing_toolbar
│ └── main_collapsing_toolbar.dart
├── communication_widgets
│ ├── child1_page.dart
│ ├── child2_page.dart
│ ├── main_communication_widgets.dart
│ └── parent_page.dart
├── fetch_data
│ ├── main_fetch_data.dart
│ └── photo.dart
├── hero_animations
│ ├── hero_dialog_route.dart
│ ├── main_hero_animations.dart
│ ├── page1.dart
│ └── page2.dart
├── main.dart
├── menu_navigations
│ ├── content_navigation.dart
│ ├── header_navigation
│ │ ├── header_navigation.dart
│ │ └── main_header_navigation.dart
│ └── main_menu_navigations.dart
├── persistent_tabbar
│ ├── main_persistent_tabbar.dart
│ ├── page1.dart
│ └── page2.dart
├── scroll_controller
│ ├── main_scroll_controller.dart
│ ├── scroll_limit_reached.dart
│ ├── scroll_movement.dart
│ ├── scroll_status.dart
│ └── scroll_sync
│ │ └── scroll_sync.dart
├── size_and_position
│ └── main_size_and_position.dart
└── split_image
│ └── main_split_image.dart
├── pubspec.yaml
├── test
└── widget_test.dart
└── web
└── index.html
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Flutter CI
2 |
3 | # This workflow is triggered on pushes to the repository.
4 |
5 | on:
6 | push:
7 | branches:
8 | - master
9 |
10 | # on: push # Default will running for every branch.
11 |
12 | jobs:
13 | build:
14 | # This job will run on ubuntu virtual machine
15 | runs-on: ubuntu-latest
16 | steps:
17 |
18 | # Setup Java environment in order to build the Android app.
19 | - uses: actions/checkout@v1
20 | - uses: actions/setup-java@v1
21 | with:
22 | java-version: '12.x'
23 |
24 | # Setup the flutter environment.
25 | - uses: subosito/flutter-action@v1
26 | with:
27 | channel: 'stable'
28 | # flutter-version: '1.12.x' # you can also specify exact version of flutter
29 |
30 | # Get flutter dependencies.
31 | - run: flutter pub get
32 |
33 | # Statically analyze the Dart code for any errors.
34 | - run: flutter analyze .
35 |
36 | # Build apk.
37 | - run: flutter build apk
38 |
39 | # Upload generated apk to the artifacts.
40 | - uses: actions/upload-artifact@v1
41 | with:
42 | name: release-apk
43 | path: build/app/outputs/apk/release/app-release.apk
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .classpath
21 | .project
22 | .settings/
23 | .vscode/
24 |
25 | # Flutter repo-specific
26 | /bin/cache/
27 | /bin/mingit/
28 | /dev/benchmarks/mega_gallery/
29 | /dev/bots/.recipe_deps
30 | /dev/bots/android_tools/
31 | /dev/docs/doc/
32 | /dev/docs/flutter.docs.zip
33 | /dev/docs/lib/
34 | /dev/docs/pubspec.yaml
35 | /dev/integration_tests/**/xcuserdata
36 | /dev/integration_tests/**/Pods
37 | /packages/flutter/coverage/
38 | version
39 |
40 | # packages file containing multi-root paths
41 | .packages.generated
42 |
43 | # Flutter/Dart/Pub related
44 | **/doc/api/
45 | .dart_tool/
46 | .flutter-plugins
47 | .flutter-plugins-dependencies
48 | .packages
49 | .pub-cache/
50 | .pub/
51 | build/
52 | flutter_*.png
53 | linked_*.ds
54 | unlinked.ds
55 | unlinked_spec.ds
56 |
57 | # Android related
58 | **/android/**/gradle-wrapper.jar
59 | **/android/.gradle
60 | **/android/captures/
61 | **/android/gradlew
62 | **/android/gradlew.bat
63 | **/android/local.properties
64 | **/android/**/GeneratedPluginRegistrant.java
65 | **/android/key.properties
66 | *.jks
67 |
68 | # iOS/XCode related
69 | **/ios/**/*.mode1v3
70 | **/ios/**/*.mode2v3
71 | **/ios/**/*.moved-aside
72 | **/ios/**/*.pbxuser
73 | **/ios/**/*.perspectivev3
74 | **/ios/**/*sync/
75 | **/ios/**/.sconsign.dblite
76 | **/ios/**/.tags*
77 | **/ios/**/.vagrant/
78 | **/ios/**/DerivedData/
79 | **/ios/**/Icon?
80 | **/ios/**/Pods/
81 | **/ios/**/.symlinks/
82 | **/ios/**/profile
83 | **/ios/**/xcuserdata
84 | **/ios/.generated/
85 | **/ios/Flutter/App.framework
86 | **/ios/Flutter/Flutter.framework
87 | **/ios/Flutter/Flutter.podspec
88 | **/ios/Flutter/Generated.xcconfig
89 | **/ios/Flutter/app.flx
90 | **/ios/Flutter/app.zip
91 | **/ios/Flutter/flutter_assets/
92 | **/ios/Flutter/flutter_export_environment.sh
93 | **/ios/ServiceDefinitions.json
94 | **/ios/Runner/GeneratedPluginRegistrant.*
95 |
96 | # macOS
97 | **/macos/Flutter/GeneratedPluginRegistrant.swift
98 | **/macos/Flutter/Flutter-Debug.xcconfig
99 | **/macos/Flutter/Flutter-Release.xcconfig
100 | **/macos/Flutter/Flutter-Profile.xcconfig
101 |
102 | # Coverage
103 | coverage/
104 |
105 | # Exceptions to above rules.
106 | !**/ios/**/default.mode1v3
107 | !**/ios/**/default.mode2v3
108 | !**/ios/**/default.pbxuser
109 | !**/ios/**/default.perspectivev3
110 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
111 | !/dev/ci/**/Gemfile.lock
--------------------------------------------------------------------------------
/.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: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b
8 | channel: beta
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2019 Diego Velásquez.
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
13 | all 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
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | *.class
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 | GeneratedPluginRegistrant.java
11 |
--------------------------------------------------------------------------------
/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 | apply plugin: 'com.android.application'
15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
16 |
17 | android {
18 | compileSdkVersion 29
19 | buildToolsVersion '27.0.3'
20 |
21 | lintOptions {
22 | disable 'InvalidPackage'
23 | }
24 |
25 | defaultConfig {
26 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
27 | applicationId "com.example.flutter_samples"
28 | minSdkVersion 16
29 | targetSdkVersion 29
30 | versionCode 1
31 | versionName "1.0"
32 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
33 | }
34 |
35 | buildTypes {
36 | release {
37 | // TODO: Add your own signing config for the release build.
38 | // Signing with the debug keys for now, so `flutter run --release` works.
39 | signingConfig signingConfigs.debug
40 | }
41 | }
42 | }
43 |
44 | flutter {
45 | source '../..'
46 | }
47 |
48 | dependencies {
49 | testImplementation 'junit:junit:4.12'
50 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
51 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
52 | }
53 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/android/app/src/main/java/com/example/flutter_samples/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.flutter_samples;
2 |
3 | import android.os.Bundle;
4 | import io.flutter.app.FlutterActivity;
5 | import io.flutter.plugins.GeneratedPluginRegistrant;
6 |
7 | import android.view.ViewTreeObserver;
8 | import android.view.WindowManager;
9 |
10 | public class MainActivity extends FlutterActivity {
11 | @Override
12 | protected void onCreate(Bundle savedInstanceState) {
13 | super.onCreate(savedInstanceState);
14 | //make transparent status bar
15 | getWindow().setStatusBarColor(0x00000000);
16 | GeneratedPluginRegistrant.registerWith(this);
17 | //Remove full screen flag after load
18 | ViewTreeObserver vto = getFlutterView().getViewTreeObserver();
19 | vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
20 | @Override
21 | public void onGlobalLayout() {
22 | getFlutterView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
23 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
24 | }
25 | });
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/flutter_samples/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.flutter_samples
2 |
3 | import androidx.annotation.NonNull;
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/mario_head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/drawable/mario_head.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | #FF0000
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.5.3'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
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.enableR8=true
3 | android.useAndroidX=true
4 | android.enableJetifier=true
--------------------------------------------------------------------------------
/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-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/assets/chango.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/assets/chango.png
--------------------------------------------------------------------------------
/assets/monkey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/assets/monkey.png
--------------------------------------------------------------------------------
/images/balls/ball1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/balls/ball1.png
--------------------------------------------------------------------------------
/images/balls/ball2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/balls/ball2.png
--------------------------------------------------------------------------------
/images/balls/ball3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/balls/ball3.png
--------------------------------------------------------------------------------
/images/balls/ball4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/balls/ball4.png
--------------------------------------------------------------------------------
/images/characters/boo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/boo.png
--------------------------------------------------------------------------------
/images/characters/broly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/broly.png
--------------------------------------------------------------------------------
/images/characters/cell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/cell.png
--------------------------------------------------------------------------------
/images/characters/frieza.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/frieza.png
--------------------------------------------------------------------------------
/images/characters/gohan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/gohan.png
--------------------------------------------------------------------------------
/images/characters/goku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/goku.png
--------------------------------------------------------------------------------
/images/characters/vegeta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/characters/vegeta.png
--------------------------------------------------------------------------------
/images/credit_cards/chip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/credit_cards/chip.png
--------------------------------------------------------------------------------
/images/credit_cards/chip_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/credit_cards/chip_logo.png
--------------------------------------------------------------------------------
/images/dash_dart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/dash_dart.png
--------------------------------------------------------------------------------
/images/dash_dart_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/dash_dart_dark.png
--------------------------------------------------------------------------------
/images/mario_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/mario_logo.png
--------------------------------------------------------------------------------
/images/mesi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/mesi.png
--------------------------------------------------------------------------------
/images/shoes/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/shoes/1.png
--------------------------------------------------------------------------------
/images/shoes/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/shoes/2.png
--------------------------------------------------------------------------------
/images/shoes/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/shoes/3.png
--------------------------------------------------------------------------------
/images/shoes/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/shoes/4.png
--------------------------------------------------------------------------------
/images/twitter_flutter_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/twitter_flutter_bg.png
--------------------------------------------------------------------------------
/images/twitter_flutter_logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/images/twitter_flutter_logo.jpg
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/app.flx
37 | /Flutter/app.zip
38 | /Flutter/flutter_assets/
39 | /Flutter/App.framework
40 | /Flutter/Flutter.framework
41 | /Flutter/Generated.xcconfig
42 | /ServiceDefinitions.json
43 |
44 | Pods/
45 | .symlinks/
46 |
--------------------------------------------------------------------------------
/ios/Flutter/.last_build_id:
--------------------------------------------------------------------------------
1 | d6f54622ecce475d1a4258a08adc432e
--------------------------------------------------------------------------------
/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 | 11.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/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '11.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
32 | end
33 |
34 | post_install do |installer|
35 | installer.pods_project.targets.each do |target|
36 | flutter_additional_ios_build_settings(target)
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | UIApplication.sharedApplication.statusBarHidden = false;
9 | [GeneratedPluginRegistrant registerWithRegistry:self];
10 | // Override point for customization after application launch.
11 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
12 | }
13 |
14 | @end
15 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/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/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/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/Assets.xcassets/mario_head.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "mario_head.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/mario_head.imageset/mario_head.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diegoveloper/flutter-samples/9aac040f5657eb0937fd00628d3becd7f128aff5/ios/Runner/Assets.xcassets/mario_head.imageset/mario_head.png
--------------------------------------------------------------------------------
/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 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/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 | flutter_samples
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIStatusBarHidden
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UISupportedInterfaceOrientations~ipad
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationPortraitUpsideDown
41 | UIInterfaceOrientationLandscapeLeft
42 | UIInterfaceOrientationLandscapeRight
43 |
44 | UIViewControllerBasedStatusBarAppearance
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
--------------------------------------------------------------------------------
/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/animations/circular_list/circular_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:circle_wheel_scroll/circle_wheel_scroll_view.dart' as wheel;
3 | import 'package:flutter_samples/animations/list_details/character.dart';
4 |
5 | class CircularListPage extends StatefulWidget {
6 | @override
7 | _CircularListPageState createState() => _CircularListPageState();
8 | }
9 |
10 | class _CircularListPageState extends State {
11 | late wheel.FixedExtentScrollController _controller;
12 |
13 | _listListener() {
14 | setState(() {});
15 | }
16 |
17 | @override
18 | void initState() {
19 | _controller = wheel.FixedExtentScrollController();
20 | _controller.addListener(_listListener);
21 | super.initState();
22 | }
23 |
24 | @override
25 | void dispose() {
26 | _controller.removeListener(_listListener);
27 | _controller.dispose();
28 | super.dispose();
29 | }
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return Scaffold(
34 | backgroundColor: Color(0xFF2F6FE0),
35 | appBar: AppBar(
36 | title: Text("Circular List"),
37 | ),
38 | body: wheel.CircleListScrollView.useDelegate(
39 | childDelegate: wheel.CircleListChildBuilderDelegate(
40 | builder: (context, index) {
41 | int currentIndex = 0;
42 | try {
43 | currentIndex = _controller.selectedItem;
44 | } catch (_) {}
45 | final num resizeFactor =
46 | (1 - (((currentIndex - index).abs() * 0.3).clamp(0.0, 1.0)));
47 | return CircleListItem(
48 | resizeFactor: resizeFactor as double?,
49 | character: characters[index],
50 | );
51 | },
52 | childCount: characters.length,
53 | ),
54 | physics: wheel.CircleFixedExtentScrollPhysics(),
55 | controller: _controller,
56 | axis: Axis.vertical,
57 | itemExtent: 120,
58 | radius: MediaQuery.of(context).size.width * 0.8,
59 | ),
60 | );
61 | }
62 | }
63 |
64 | class CircleListItem extends StatelessWidget {
65 | final double? resizeFactor;
66 | final Character? character;
67 |
68 | const CircleListItem({Key? key, this.resizeFactor, this.character})
69 | : super(key: key);
70 |
71 | @override
72 | Widget build(BuildContext context) {
73 | return Center(
74 | child: Row(mainAxisSize: MainAxisSize.min, children: [
75 | Padding(
76 | padding: const EdgeInsets.all(15.0),
77 | child: Text(
78 | character!.title!,
79 | style: TextStyle(
80 | color: Colors.white,
81 | fontSize: 22 * resizeFactor!,
82 | ),
83 | ),
84 | ),
85 | Container(
86 | width: 120 * resizeFactor!,
87 | height: 120 * resizeFactor!,
88 | decoration: BoxDecoration(
89 | borderRadius: BorderRadius.circular(60),
90 | color: Colors.white,
91 | ),
92 | child: Align(
93 | child: Container(
94 | child: Image.asset(
95 | character!.avatar!,
96 | fit: BoxFit.contain,
97 | ),
98 | decoration: BoxDecoration(
99 | borderRadius: BorderRadius.circular(60),
100 | color: Colors.blue,
101 | ),
102 | height: 110 * resizeFactor!,
103 | width: 110 * resizeFactor!,
104 | ),
105 | ),
106 | ),
107 | ]),
108 | );
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/animations/custom_appbar/my_custom_appbar_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MyCustomAppBarPage extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) => Scaffold(
6 | body: SafeArea(
7 | child: CustomScrollView(
8 | slivers: [
9 | SliverPersistentHeader(
10 | pinned: true,
11 | delegate: CustomSliverDelegate(
12 | expandedHeight: 150,
13 | title: "My Custom AppBar",
14 | description: "SliverPersistentHeader",
15 | ),
16 | ),
17 | SliverFillRemaining(
18 | child: Center(
19 | child: Padding(
20 | padding: const EdgeInsets.all(15),
21 | child: Image.asset("images/characters/goku.png"),
22 | ),
23 | ),
24 | ),
25 | ],
26 | ),
27 | ),
28 | );
29 | }
30 |
31 | class CustomSliverDelegate extends SliverPersistentHeaderDelegate {
32 | final double expandedHeight;
33 | final bool hideTitleWhenExpanded;
34 | final String title;
35 | final String description;
36 |
37 | CustomSliverDelegate({
38 | required this.expandedHeight,
39 | this.hideTitleWhenExpanded = true,
40 | this.title = "",
41 | this.description = "",
42 | });
43 |
44 | @override
45 | Widget build(
46 | BuildContext context, double shrinkOffset, bool overlapsContent) {
47 | final appBarSize = expandedHeight - shrinkOffset;
48 | final cardTopPosition = expandedHeight / 2 - shrinkOffset;
49 | final factor = 2 - (expandedHeight / appBarSize);
50 | final percent = factor < 0 || factor > 1 ? 0.0 : factor;
51 | return SizedBox(
52 | height: expandedHeight + expandedHeight / 2,
53 | child: Stack(
54 | children: [
55 | SizedBox(
56 | height: appBarSize < kToolbarHeight ? kToolbarHeight : appBarSize,
57 | child: AppBar(
58 | backgroundColor: Colors.green,
59 | leading: BackButton(),
60 | elevation: 0.0,
61 | title: Opacity(
62 | opacity: hideTitleWhenExpanded ? 1.0 - percent : 1.0,
63 | child: Text(title),
64 | ),
65 | ),
66 | ),
67 | Positioned(
68 | left: 0.0,
69 | right: 0.0,
70 | top: cardTopPosition > 0 ? cardTopPosition : 0,
71 | bottom: 0.0,
72 | child: Opacity(
73 | opacity: percent,
74 | child: Padding(
75 | padding: EdgeInsets.symmetric(horizontal: 30 * percent),
76 | child: Card(
77 | elevation: 10.0,
78 | child: Center(
79 | child: Padding(
80 | padding: const EdgeInsets.all(18.0),
81 | child: Text(
82 | description,
83 | textAlign: TextAlign.center,
84 | style: Theme.of(context).textTheme.headline6,
85 | ),
86 | ),
87 | ),
88 | ),
89 | ),
90 | ),
91 | ),
92 | ],
93 | ),
94 | );
95 | }
96 |
97 | @override
98 | double get maxExtent => expandedHeight + expandedHeight / 2;
99 |
100 | @override
101 | double get minExtent => kToolbarHeight;
102 |
103 | @override
104 | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
105 | return true;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/lib/animations/custom_sliverheader/custom_sliver_header.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | class CustomSliverHeader extends StatefulWidget {
6 | @override
7 | CustomSliverHeaderState createState() {
8 | return CustomSliverHeaderState();
9 | }
10 | }
11 |
12 | const avatarSize = 60.0;
13 | const minAvatarSize = 30.0;
14 | const extraSpace = 70.0;
15 |
16 | class CustomSliverHeaderState extends State {
17 | @override
18 | Widget build(BuildContext context) {
19 | return Theme(
20 | data: ThemeData.dark(),
21 | child: Material(
22 | color: Color(0XFF181818),
23 | child: SafeArea(
24 | child: NestedScrollView(
25 | headerSliverBuilder: (context, innerBoxIsScrolled) {
26 | return [
27 | SliverPersistentHeader(
28 | delegate: MyHeaderDelegate(
29 | kToolbarHeight + avatarSize + extraSpace),
30 | pinned: true,
31 | ),
32 | ];
33 | },
34 | body: ListView.builder(
35 | itemBuilder: (context, index) => ListTile(
36 | title: Text("Item $index"),
37 | ),
38 | itemCount: 20,
39 | ),
40 | ),
41 | ),
42 | ),
43 | );
44 | }
45 | }
46 |
47 | class MyHeaderDelegate extends SliverPersistentHeaderDelegate {
48 | final double extendedHeight;
49 |
50 | MyHeaderDelegate(this.extendedHeight);
51 |
52 | @override
53 | Widget build(
54 | BuildContext context, double shrinkOffset, bool overlapsContent) {
55 | // print("shrinkOffset: $shrinkOffset ... $overlapsContent");
56 | double newSize = maxExtent - shrinkOffset;
57 | double newSizePercent = avatarSize + extraSpace - shrinkOffset;
58 | double newAvatarSize = avatarSize - shrinkOffset;
59 | double newAvatarSpace = avatarSize - shrinkOffset;
60 | if (newSize < minExtent) {
61 | newSize = minExtent;
62 | }
63 | if (newAvatarSize < minAvatarSize) {
64 | newAvatarSize = minAvatarSize;
65 | }
66 | if (newAvatarSpace < 0) {
67 | newAvatarSpace = 0;
68 | }
69 | final percent = (newSizePercent >= 0 ? newSizePercent : 0) /
70 | (avatarSize + extraSpace).abs();
71 | double avatarXPosition = max(
72 | ((MediaQuery.of(context).size.width / 2) - newAvatarSize / 2) * percent,
73 | 15);
74 |
75 | double actionsXPosition = 50 * (1 - percent);
76 |
77 | return Container(
78 | color: Color(0xFF2C2E2F),
79 | child: Column(
80 | mainAxisSize: MainAxisSize.min,
81 | children: [
82 | Container(
83 | height: kToolbarHeight + newAvatarSpace,
84 | child: Stack(
85 | children: [
86 | AppBar(
87 | title: Text("Google"),
88 | centerTitle: false,
89 | elevation: 0.0,
90 | actions: [
91 | Container(
92 | width: 150,
93 | child: Stack(
94 | fit: StackFit.expand,
95 | children: [
96 | Positioned(
97 | top: 0,
98 | right: actionsXPosition,
99 | child: Row(
100 | mainAxisSize: MainAxisSize.min,
101 | children: [
102 | IconButton(
103 | icon: Icon(Icons.help),
104 | onPressed: () => null,
105 | ),
106 | IconButton(
107 | icon: Icon(Icons.more_vert),
108 | onPressed: () => null,
109 | ),
110 | ],
111 | ),
112 | )
113 | ],
114 | ),
115 | ),
116 | ],
117 | backgroundColor: Colors.transparent,
118 | ),
119 | Positioned(
120 | bottom: minAvatarSize / 2,
121 | right: avatarXPosition,
122 | child: CircleAvatar(
123 | radius: newAvatarSize / 2,
124 | backgroundColor: Colors.red,
125 | ),
126 | )
127 | ],
128 | ),
129 | ),
130 | Expanded(
131 | child: Opacity(
132 | opacity: percent,
133 | child: Column(mainAxisSize: MainAxisSize.min, children: [
134 | Expanded(
135 | child: Text("Full Name",
136 | style: Theme.of(context).textTheme.headline4)),
137 | Expanded(
138 | child: Text("email@email.com",
139 | style: Theme.of(context).textTheme.headline6),
140 | )
141 | ]),
142 | ),
143 | ),
144 | ],
145 | ),
146 | );
147 | }
148 |
149 | @override
150 | double get maxExtent => extendedHeight;
151 |
152 | @override
153 | double get minExtent => kToolbarHeight;
154 |
155 | @override
156 | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
157 | }
158 |
--------------------------------------------------------------------------------
/lib/animations/hide_my_widgets/hide_my_widget.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'dart:typed_data';
3 | import 'package:vector_math/vector_math.dart' as vector;
4 | import 'package:flutter/material.dart';
5 | import 'package:flutter/physics.dart';
6 | import 'package:flutter/rendering.dart';
7 | import 'dart:ui' as ui;
8 |
9 | class HideMyWidget extends StatefulWidget {
10 | final Widget? child;
11 |
12 | const HideMyWidget({Key? key, this.child}) : super(key: key);
13 |
14 | @override
15 | _HideMyWidgetState createState() => _HideMyWidgetState();
16 | }
17 |
18 | class _HideMyWidgetState extends State with SingleTickerProviderStateMixin {
19 | bool _hide = false;
20 | final _key = GlobalKey();
21 | late AnimationController _animationController;
22 | OverlayEntry? _entry;
23 |
24 | void _onTap() async {
25 | RenderRepaintBoundary boundary = _key.currentContext!.findRenderObject() as RenderRepaintBoundary;
26 | ui.Image image = await boundary.toImage();
27 | final byteData = (await image.toByteData(format: ui.ImageByteFormat.png) as ByteData);
28 | var pngBytes = byteData.buffer.asUint8List();
29 |
30 | final renderBox = _key.currentContext!.findRenderObject() as RenderBox;
31 | final position = renderBox.localToGlobal(Offset.zero);
32 |
33 | _entry?.remove();
34 |
35 | final fullHeight = MediaQuery.of(context).size.height;
36 | final distance = fullHeight - position.dy;
37 | final min = 10, max = 40;
38 | final random = min + Random().nextInt(max - min);
39 | _entry = new OverlayEntry(
40 | builder: (context) {
41 | return Positioned(
42 | top: position.dy + (_animationController.value * distance),
43 | left: position.dx,
44 | width: renderBox.size.width,
45 | height: renderBox.size.height,
46 | child: Transform(
47 | transform: Matrix4.identity()..rotateZ(vector.radians(random * _animationController.value)),
48 | child: Image.memory(pngBytes),
49 | ),
50 | );
51 | },
52 | );
53 |
54 | Overlay.of(context)!.insert(_entry!);
55 | await Future.delayed(const Duration(milliseconds: 20));
56 | setState(() {
57 | _hide = true;
58 | });
59 |
60 | final simulation = GravitySimulation(
61 | position.dy / 10, // acceleration
62 | 0, // starting point
63 | 1, // end point
64 | 0, // starting velocity
65 | );
66 | _animationController.animateWith(simulation);
67 | }
68 |
69 | @override
70 | void didUpdateWidget(HideMyWidget oldWidget) {
71 | setState(() {
72 | _hide = false;
73 | });
74 | super.didUpdateWidget(oldWidget);
75 | }
76 |
77 | void _animationListener() {
78 | if (_animationController.status == AnimationStatus.completed) {
79 | _entry!.remove();
80 | _entry = null;
81 | } else {
82 | _entry!.markNeedsBuild();
83 | }
84 | }
85 |
86 | @override
87 | void initState() {
88 | _animationController = AnimationController(
89 | vsync: this,
90 | );
91 | _animationController.addListener(_animationListener);
92 | super.initState();
93 | }
94 |
95 | @override
96 | void dispose() {
97 | _animationController.removeListener(_animationListener);
98 | _animationController.dispose();
99 | super.dispose();
100 | }
101 |
102 | @override
103 | Widget build(BuildContext context) {
104 | return GestureDetector(
105 | onTap: _hide ? null : _onTap,
106 | child: Visibility(
107 | visible: !_hide,
108 | child: RepaintBoundary(
109 | key: _key,
110 | child: Container(
111 | child: AbsorbPointer(
112 | child: widget.child,
113 | ),
114 | ),
115 | ),
116 | ),
117 | );
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/lib/animations/hide_my_widgets/main_hide_my_widgets.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/hide_my_widgets/hide_my_widget.dart';
3 |
4 | class MainHideMyWidgets extends StatefulWidget {
5 | @override
6 | _MainHideMyWidgetsState createState() => _MainHideMyWidgetsState();
7 | }
8 |
9 | class _MainHideMyWidgetsState extends State {
10 | @override
11 | Widget build(BuildContext context) {
12 | return Scaffold(
13 | appBar: AppBar(
14 | elevation: 0,
15 | title: Text("Don't touch my widgets!"),
16 | backgroundColor: Colors.red,
17 | actions: [
18 | IconButton(
19 | icon: Icon(Icons.refresh),
20 | onPressed: () {
21 | setState(() {});
22 | },
23 | )
24 | ],
25 | ),
26 | body: Stack(
27 | fit: StackFit.expand,
28 | children: [
29 | Container(
30 | color: Colors.black,
31 | child: Image.asset(
32 | "images/dash_dart_dark.png",
33 | fit: BoxFit.contain,
34 | ),
35 | ),
36 | HideMyWidget(
37 | child: DecoratedBox(
38 | decoration: BoxDecoration(
39 | gradient: LinearGradient(
40 | begin: Alignment.topLeft,
41 | end: Alignment.bottomRight,
42 | stops: [
43 | 0,
44 | 0.5,
45 | 1,
46 | ],
47 | colors: [
48 | Color.fromARGB(255, 178, 19, 19),
49 | Color.fromARGB(255, 181, 49, 49),
50 | Color.fromARGB(255, 89, 10, 10),
51 | ],
52 | ),
53 | ),
54 | ),
55 | ),
56 | _myBody(),
57 | ],
58 | ));
59 | }
60 |
61 | Widget _myBody() {
62 | return Column(
63 | children: [
64 | Spacer(),
65 | Expanded(
66 | flex: 4,
67 | child: FractionallySizedBox(
68 | widthFactor: .6,
69 | child: HideMyWidget(
70 | child: FlutterLogo(),
71 | ),
72 | ),
73 | ),
74 | Expanded(
75 | flex: 1,
76 | child: Container(
77 | child: HideMyWidget(
78 | child: Text(
79 | "Welcome \nThe Dart Side",
80 | textAlign: TextAlign.center,
81 | style: TextStyle(fontSize: 24, color: Colors.white),
82 | ),
83 | ),
84 | ),
85 | ),
86 | const SizedBox(
87 | height: 30,
88 | ),
89 | Expanded(
90 | child: Padding(
91 | padding: const EdgeInsets.symmetric(horizontal: 20),
92 | child: HideMyWidget(
93 | child: TextField(
94 | decoration: InputDecoration(
95 | hintText: "Username",
96 | fillColor: Colors.white,
97 | filled: true,
98 | ),
99 | ),
100 | ),
101 | ),
102 | ),
103 | Expanded(
104 | flex: 3,
105 | child: Center(
106 | child: HideMyWidget(
107 | child: Container(
108 | padding:
109 | const EdgeInsets.symmetric(vertical: 20, horizontal: 50),
110 | decoration: BoxDecoration(
111 | color: Colors.white70,
112 | borderRadius: BorderRadius.all(Radius.circular(20)),
113 | ),
114 | child: Text(
115 | 'Login',
116 | style: TextStyle(color: Colors.black),
117 | ),
118 | ),
119 | ),
120 | ),
121 | ),
122 | ],
123 | );
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/lib/animations/list_details/character.dart:
--------------------------------------------------------------------------------
1 | class Character {
2 | final String? avatar;
3 | final String? title;
4 | final String? description;
5 | final int? color;
6 |
7 | Character({
8 | this.avatar,
9 | this.title,
10 | this.description,
11 | this.color,
12 | });
13 | }
14 |
15 | //source: https://www.giantbomb.com/dragon-ball-z/3025-159/characters/
16 | final characters = [
17 | Character(
18 | title: "Goku",
19 | description:
20 | "Goku is the main protagonist in the Dragon Ball franchise and one of the strongest fighters in the universe. He is a Saiyan warrior whose original name was Kakarot, son of Bardock. He is the husband of Chi Chi, and the father of Gohan and Goten. He is also Grandfather to Pan.",
21 | avatar: "images/characters/goku.png",
22 | color: 0xFFE83835,
23 | ),
24 | Character(
25 | title: "Vegeta",
26 | description:
27 | "The Prince of all Saiyans, Vegeta is an incredibly strong elite Saiyan warrior. In his constant struggle to surpass his eternal rival Goku, he has become one of the most powerful fighters in the universe.",
28 | avatar: "images/characters/vegeta.png",
29 | color: 0xFF238BD0,
30 | ),
31 | Character(
32 | title: "Gohan",
33 | description:
34 | "Gohan is Goku's son and one of the heroes in the Dragon Ball Z universe. He is also the protagonist of the Cell Saga, where he is the first to reach the Super Saiyan 2 form, through immense anger and emotion. In his later Ultimate form, he is considered the most powerful warrior in Dragon Ball Z. He is Goten's older brother and the father of Pan. His wife is Videl and his grandfathers are Ox-king and Bardock, respectively.",
35 | avatar: "images/characters/gohan.png",
36 | color: 0xFF354C6C,
37 | ),
38 | Character(
39 | title: "Frieza",
40 | description:
41 | "In the Dragon Ball Z universe, Frieza is one of the first villains to really test Goku.",
42 | avatar: "images/characters/frieza.png",
43 | color: 0xFF6F2B62,
44 | ),
45 | Character(
46 | title: "Cell",
47 | description:
48 | "Cell is an android constructed from cells taken from various fighters of the Dragon Ball Z universe. He is the main antagonist of the Android Saga of Dragon Ball.",
49 | avatar: "images/characters/cell.png",
50 | color: 0xFF447C12,
51 | ),
52 | Character(
53 | title: "Majin Buu",
54 | description:
55 | "One of Dragon Ball Z's most ferocious and transformation-happy of characters, Majin Buu is the last major enemy in the Dragon Ball Z storyline. With the ability to absorb foes, learn moves, and deliver a serious punch, Majin Buu is one of Goku and friends' most challenging of enemies.",
56 | avatar: "images/characters/boo.png",
57 | color: 0xFFE7668E,
58 | ),
59 | Character(
60 | title: "Broly",
61 | description:
62 | "The Legendary Super Saiyan from myth, Broly is one of the Dragon Ball Z franchise's most powerful and destructive Saiyan villains.",
63 | avatar: "images/characters/broly.png",
64 | color: 0xFFBD9158,
65 | ),
66 | ];
67 |
--------------------------------------------------------------------------------
/lib/animations/list_details/detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/list_details/character.dart';
3 |
4 | class DetailPage extends StatefulWidget {
5 | final Character character;
6 |
7 | const DetailPage({
8 | Key? key,
9 | required this.character,
10 | }) : super(key: key);
11 |
12 | @override
13 | _DetailPageState createState() => _DetailPageState();
14 | }
15 |
16 | class _DetailPageState extends State
17 | with SingleTickerProviderStateMixin {
18 | late AnimationController _controller;
19 |
20 | @override
21 | void initState() {
22 | _controller =
23 | AnimationController(vsync: this, duration: Duration(milliseconds: 500));
24 | _controller.forward();
25 | super.initState();
26 | }
27 |
28 | @override
29 | void dispose() {
30 | _controller.dispose();
31 | super.dispose();
32 | }
33 |
34 | @override
35 | Widget build(BuildContext context) {
36 | return Stack(
37 | children: [
38 | Hero(
39 | tag: "background_${widget.character.title}",
40 | child: Container(
41 | color: Color(widget.character.color!),
42 | ),
43 | ),
44 | Scaffold(
45 | backgroundColor: Colors.transparent,
46 | appBar: AppBar(
47 | backgroundColor: Color(widget.character.color!),
48 | elevation: 0,
49 | title: Text(widget.character.title!),
50 | leading: CloseButton(),
51 | ),
52 | body: SingleChildScrollView(
53 | child: Column(
54 | crossAxisAlignment: CrossAxisAlignment.stretch,
55 | children: [
56 | Hero(
57 | tag: "image_${widget.character.title}",
58 | child: Image.asset(
59 | widget.character.avatar!,
60 | height: MediaQuery.of(context).size.height / 2,
61 | ),
62 | ),
63 | AnimatedBuilder(
64 | animation: _controller,
65 | builder: (context, widget) => Transform.translate(
66 | transformHitTests: false,
67 | offset: Offset.lerp(
68 | Offset(0.0, 200.0), Offset.zero, _controller.value)!,
69 | child: widget,
70 | ),
71 | child: Padding(
72 | padding: EdgeInsets.all(10),
73 | child: Text(
74 | widget.character.description!,
75 | style: TextStyle(
76 | fontSize: 18,
77 | color: Colors.white,
78 | fontWeight: FontWeight.w400,
79 | ),
80 | ),
81 | ),
82 | ),
83 | ],
84 | ),
85 | ),
86 | )
87 | ],
88 | );
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/lib/animations/list_details/list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/list_details/character.dart';
3 | import 'package:flutter_samples/animations/list_details/detail_page.dart';
4 |
5 | class ListPage extends StatefulWidget {
6 | @override
7 | _ListPageState createState() => _ListPageState();
8 | }
9 |
10 | class _ListPageState extends State {
11 | PageController? _controller;
12 |
13 | _goToDetail(Character character) {
14 | final page = DetailPage(character: character);
15 | Navigator.of(context).push(
16 | PageRouteBuilder(
17 | pageBuilder: (BuildContext context, Animation animation,
18 | Animation secondaryAnimation) {
19 | return AnimatedBuilder(
20 | animation: animation,
21 | builder: (BuildContext context, Widget? child) {
22 | return Opacity(
23 | opacity: animation.value,
24 | child: page,
25 | );
26 | });
27 | },
28 | transitionDuration: Duration(milliseconds: 400)),
29 | );
30 | }
31 |
32 | _pageListener() {
33 | setState(() {});
34 | }
35 |
36 | @override
37 | void initState() {
38 | _controller = PageController(viewportFraction: 0.6);
39 | _controller!.addListener(_pageListener);
40 | super.initState();
41 | }
42 |
43 | @override
44 | void dispose() {
45 | _controller!.removeListener(_pageListener);
46 | _controller!.dispose();
47 | super.dispose();
48 | }
49 |
50 | @override
51 | Widget build(BuildContext context) {
52 | return Scaffold(
53 | appBar: AppBar(
54 | title: Text("Dragon Ball"),
55 | backgroundColor: Colors.black54,
56 | ),
57 | body: PageView.builder(
58 | scrollDirection: Axis.vertical,
59 | controller: _controller,
60 | itemCount: characters.length,
61 | itemBuilder: (context, index) {
62 | double? currentPage = 0;
63 | try {
64 | currentPage = _controller!.page;
65 | } catch (_) {}
66 |
67 | final num resizeFactor =
68 | (1 - (((currentPage! - index).abs() * 0.3).clamp(0.0, 1.0)));
69 | final currentCharacter = characters[index];
70 | return ListItem(
71 | character: currentCharacter,
72 | resizeFactor: resizeFactor as double,
73 | onTap: () => _goToDetail(currentCharacter),
74 | );
75 | }),
76 | );
77 | }
78 | }
79 |
80 | class ListItem extends StatelessWidget {
81 | final Character character;
82 | final double resizeFactor;
83 | final VoidCallback onTap;
84 |
85 | const ListItem({
86 | Key? key,
87 | required this.character,
88 | required this.resizeFactor,
89 | required this.onTap,
90 | }) : super(key: key);
91 |
92 | @override
93 | Widget build(BuildContext context) {
94 | double height = MediaQuery.of(context).size.height * 0.4;
95 | double width = MediaQuery.of(context).size.width * 0.85;
96 | return InkWell(
97 | onTap: onTap,
98 | child: Align(
99 | alignment: Alignment.topCenter,
100 | child: Container(
101 | width: width * resizeFactor,
102 | height: height * resizeFactor,
103 | child: Stack(
104 | children: [
105 | Positioned(
106 | left: 0,
107 | right: 0,
108 | top: height / 4,
109 | bottom: 0,
110 | child: Hero(
111 | tag: "background_${character.title}",
112 | child: Card(
113 | clipBehavior: Clip.antiAliasWithSaveLayer,
114 | elevation: 10,
115 | shape: RoundedRectangleBorder(
116 | borderRadius: BorderRadius.circular(15)),
117 | child: DecoratedBox(
118 | decoration: BoxDecoration(
119 | gradient: LinearGradient(
120 | begin: Alignment.topCenter,
121 | end: Alignment.bottomCenter,
122 | colors: [
123 | Color(character.color!),
124 | Colors.white,
125 | ],
126 | stops: [
127 | 0.4,
128 | 1.0,
129 | ])),
130 | child: Container(
131 | alignment: Alignment.bottomLeft,
132 | margin: EdgeInsets.only(
133 | left: 20,
134 | bottom: 10,
135 | ),
136 | child: Text(
137 | character.title!,
138 | style: TextStyle(
139 | fontSize: 24 * resizeFactor,
140 | fontWeight: FontWeight.w600,
141 | ),
142 | ),
143 | ),
144 | ),
145 | ),
146 | ),
147 | ),
148 | Align(
149 | alignment: Alignment.topRight,
150 | child: Hero(
151 | tag: "image_${character.title}",
152 | child: Image.asset(
153 | character.avatar!,
154 | width: width / 2,
155 | height: height,
156 | ),
157 | ),
158 | ),
159 | ],
160 | )),
161 | ),
162 | );
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/lib/animations/main_animations.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/circular_list/circular_list_page.dart';
3 | import 'package:flutter_samples/animations/custom_appbar/my_custom_appbar_page.dart';
4 | import 'package:flutter_samples/animations/foldable/foldable_animation.dart';
5 | import 'package:flutter_samples/animations/list_details/list_page.dart';
6 | import 'package:flutter_samples/animations/menu_exploration/main_menu_exploration.dart';
7 | import 'package:flutter_samples/animations/neon_button/neon_button_main.dart';
8 | import 'package:flutter_samples/animations/split_widget/main_split_widget.dart';
9 | import 'package:flutter_samples/animations/turn_on_the_light/turn_on_the_light.dart';
10 | import 'package:flutter_samples/main.dart';
11 |
12 | import 'custom_sliverheader/custom_sliver_header.dart';
13 | import 'hide_my_widgets/main_hide_my_widgets.dart';
14 | import 'shrink_top_list/shrink_top_list_page.dart';
15 |
16 | class MainAnimations extends StatefulWidget {
17 | @override
18 | MainAnimationsState createState() {
19 | return MainAnimationsState();
20 | }
21 | }
22 |
23 | class MainAnimationsState extends State {
24 | onButtonTap(Widget page) {
25 | Navigator.push(
26 | context, MaterialPageRoute(builder: (BuildContext context) => page));
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return Scaffold(
32 | appBar: AppBar(
33 | title: Text("Flutter Animations"),
34 | ),
35 | body: Padding(
36 | padding: EdgeInsets.all(15.0),
37 | child: ListView(
38 | children: [
39 | MyMenuButton(
40 | title: "Foldable Page",
41 | actionTap: () {
42 | onButtonTap(FoldablePage());
43 | },
44 | ),
45 | MyMenuButton(
46 | title: "List - Detail Page",
47 | actionTap: () {
48 | onButtonTap(ListPage());
49 | },
50 | ),
51 | MyMenuButton(
52 | title: "Circular List Page",
53 | actionTap: () {
54 | onButtonTap(CircularListPage());
55 | },
56 | ),
57 | MyMenuButton(
58 | title: "My Custom AppBar Page",
59 | actionTap: () {
60 | onButtonTap(MyCustomAppBarPage());
61 | },
62 | ),
63 | MyMenuButton(
64 | title: "My Custom Sliver Header",
65 | actionTap: () {
66 | onButtonTap(CustomSliverHeader());
67 | },
68 | ),
69 | MyMenuButton(
70 | title: "Split Widget",
71 | actionTap: () {
72 | onButtonTap(MainSplitWidget());
73 | },
74 | ),
75 | MyMenuButton(
76 | title: "Turn on the light",
77 | actionTap: () {
78 | onButtonTap(TurnOnTheLight());
79 | },
80 | ),
81 | MyMenuButton(
82 | title: "Hide my widgets",
83 | actionTap: () {
84 | onButtonTap(MainHideMyWidgets());
85 | },
86 | ),
87 | MyMenuButton(
88 | title: "Menu Exploration",
89 | actionTap: () {
90 | onButtonTap(MainMenuExploration());
91 | },
92 | ),
93 | MyMenuButton(
94 | title: "Shrink Top List",
95 | actionTap: () {
96 | onButtonTap(ShrinkTopListPage());
97 | },
98 | ),
99 | MyMenuButton(
100 | title: "Neon Buttons",
101 | actionTap: () {
102 | onButtonTap(NeonButonMain());
103 | },
104 | ),
105 | ],
106 | ),
107 | ),
108 | );
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/lib/animations/menu_exploration/main_menu_exploration.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'menu_exploration.dart';
3 |
4 | class MainMenuExploration extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Container(
8 | color: Colors.grey.shade800,
9 | child: Center(
10 | child: MenuExploration(
11 | options: ['Easy', 'Normal', 'Hard', 'Expert'],
12 | selectedValue: 'Expert',
13 | height: MediaQuery.of(context).size.height * 0.1,
14 | width: MediaQuery.of(context).size.width / 2,
15 | onChanged: (val) {
16 | print("Current Value: $val");
17 | },
18 | ),
19 | ),
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/animations/menu_exploration/menu_exploration.dart:
--------------------------------------------------------------------------------
1 | //Design inspired from `Oleg Frolov` https://dribbble.com/shots/6937943-Menu-Interaction-Exploration
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | const xOffsetContainer = 10.0;
6 |
7 | class MenuExploration extends StatefulWidget {
8 | final List options;
9 | final double? height;
10 | final double? width;
11 | final ValueChanged? onChanged;
12 | final String? selectedValue;
13 |
14 | MenuExploration({
15 | Key? key,
16 | required this.options,
17 | this.width,
18 | this.height,
19 | this.onChanged,
20 | this.selectedValue,
21 | }) : assert(options.isNotEmpty),
22 | super(key: key);
23 |
24 | @override
25 | _MenuExplorationState createState() => _MenuExplorationState();
26 | }
27 |
28 | class _MenuExplorationState extends State
29 | with SingleTickerProviderStateMixin {
30 | late AnimationController _controller;
31 | late Animation _animationContainer;
32 | PageController? _pageController;
33 | int _currentIndex = 0;
34 |
35 | void _onTap() {
36 | _controller.forward(from: 0.0).whenComplete(() => _controller.reverse());
37 | _pageController!.animateToPage(_currentIndex++,
38 | duration: const Duration(
39 | milliseconds: 1100,
40 | ),
41 | curve: Curves.elasticOut);
42 | }
43 |
44 | @override
45 | void initState() {
46 | super.initState();
47 | //In case it has a selected value, find the index and set it as a initial page
48 | if (widget.selectedValue != null) {
49 | final index = widget.options.indexWhere(
50 | (item) => item.toLowerCase() == widget.selectedValue!.toLowerCase());
51 | if (index >= 0) {
52 | _currentIndex = index;
53 | }
54 | }
55 |
56 | _pageController = PageController(initialPage: _currentIndex);
57 | _controller = AnimationController(
58 | vsync: this,
59 | duration: const Duration(milliseconds: 250),
60 | );
61 | _animationContainer = Tween(
62 | begin: 0.0,
63 | end: xOffsetContainer,
64 | ).animate(
65 | CurvedAnimation(
66 | parent: _controller,
67 | curve: Curves.easeInSine,
68 | ),
69 | );
70 | }
71 |
72 | @override
73 | void dispose() {
74 | super.dispose();
75 | _controller.dispose();
76 | _pageController!.dispose();
77 | }
78 |
79 | @override
80 | Widget build(BuildContext context) {
81 | final radius = BorderRadius.circular(12.0);
82 | return Center(
83 | child: AnimatedBuilder(
84 | animation: _controller,
85 | child: Material(
86 | borderRadius: radius,
87 | child: InkWell(
88 | borderRadius: radius,
89 | onTap: _onTap,
90 | child: SizedBox(
91 | height: widget.height,
92 | width: widget.width,
93 | child: PageView.builder(
94 | controller: _pageController,
95 | physics: const NeverScrollableScrollPhysics(),
96 | onPageChanged: (index) => widget.onChanged != null
97 | ? widget.onChanged!(widget.options[_getRealIndex(index)])
98 | : null,
99 | itemBuilder: (_, index) {
100 | final value = widget.options[_getRealIndex(index)];
101 | return Center(
102 | child: Padding(
103 | padding: const EdgeInsets.all(12),
104 | child: Row(
105 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
106 | children: [
107 | Text(
108 | value,
109 | style: TextStyle(
110 | fontWeight: FontWeight.w600,
111 | fontSize: 20,
112 | ),
113 | ),
114 | Icon(
115 | Icons.arrow_forward_ios,
116 | size: 20,
117 | ),
118 | ],
119 | ),
120 | ),
121 | );
122 | },
123 | ),
124 | ),
125 | ),
126 | ),
127 | builder: (context, child) {
128 | return Transform.translate(
129 | offset: Offset(_animationContainer.value, 0.0),
130 | child: child,
131 | );
132 | },
133 | ),
134 | );
135 | }
136 |
137 | int _getRealIndex(int index) => (index >= widget.options.length)
138 | ? _getRealIndex(index - widget.options.length)
139 | : index;
140 | }
141 |
--------------------------------------------------------------------------------
/lib/animations/neon_button/neon_button.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'dart:math' as math;
3 |
4 | class NeonButton extends StatefulWidget {
5 | final Color color;
6 | final Color textActiveColor;
7 | final String text;
8 | final Duration? duration;
9 | final VoidCallback? onTap;
10 | final bool animateAfterChanges;
11 |
12 | const NeonButton({
13 | Key? key,
14 | required this.color,
15 | required this.text,
16 | this.duration,
17 | this.onTap,
18 | this.textActiveColor = Colors.black,
19 | this.animateAfterChanges = true,
20 | }) : super(key: key);
21 | @override
22 | _NeonButtonState createState() => _NeonButtonState();
23 | }
24 |
25 | class _NeonButtonState extends State
26 | with SingleTickerProviderStateMixin {
27 | AnimationController? _controller;
28 | final ValueNotifier _notifierCompleted = ValueNotifier(false);
29 |
30 | @override
31 | void didUpdateWidget(NeonButton oldWidget) {
32 | if (widget.animateAfterChanges) {
33 | _notifierCompleted.value = false;
34 | _controller!.forward(from: 0.0);
35 | }
36 | super.didUpdateWidget(oldWidget);
37 | }
38 |
39 | @override
40 | void initState() {
41 | super.initState();
42 | _controller = AnimationController(
43 | vsync: this,
44 | duration: widget.duration ??
45 | const Duration(
46 | milliseconds: 1200,
47 | ),
48 | );
49 | _controller!.forward();
50 | _controller!.addStatusListener(
51 | (status) {
52 | if (status == AnimationStatus.completed) {
53 | _notifierCompleted.value = true;
54 | }
55 | },
56 | );
57 | }
58 |
59 | @override
60 | void dispose() {
61 | _controller!.dispose();
62 | super.dispose();
63 | }
64 |
65 | @override
66 | Widget build(BuildContext context) {
67 | const padding = 20.0;
68 | return Padding(
69 | padding: const EdgeInsets.all(padding),
70 | child: CustomPaint(
71 | painter: _NeonLinePainter(
72 | animation: _controller,
73 | color: widget.color,
74 | ),
75 | child: ValueListenableBuilder(
76 | valueListenable: _notifierCompleted,
77 | builder: (context, completed, _) {
78 | return Material(
79 | color: completed ? widget.color : Colors.transparent,
80 | child: InkWell(
81 | onTap: widget.onTap,
82 | child: AnimatedContainer(
83 | duration: const Duration(milliseconds: 300),
84 | alignment: Alignment.center,
85 | decoration: BoxDecoration(
86 | boxShadow: completed
87 | ? [
88 | BoxShadow(
89 | blurRadius: padding,
90 | spreadRadius: padding,
91 | color: widget.color.withOpacity(0.8),
92 | ),
93 | ]
94 | : null,
95 | ),
96 | child: Padding(
97 | padding: const EdgeInsets.all(padding),
98 | child: FittedBox(
99 | child: Text(
100 | widget.text,
101 | textAlign: TextAlign.center,
102 | style: TextStyle(
103 | color:
104 | completed ? widget.textActiveColor : widget.color,
105 | ),
106 | ),
107 | ),
108 | ),
109 | ),
110 | ),
111 | );
112 | },
113 | ),
114 | ),
115 | );
116 | }
117 | }
118 |
119 | class _NeonLinePainter extends CustomPainter {
120 | final Animation? animation;
121 | final Color? color;
122 |
123 | _NeonLinePainter({
124 | this.animation,
125 | this.color,
126 | }) : super(repaint: animation);
127 |
128 | @override
129 | void paint(Canvas canvas, Size size) {
130 | final rect = Offset.zero & size;
131 | final Paint paint = Paint()..color = Colors.transparent;
132 | final progress = animation!.value;
133 | if (progress > 0.0) {
134 | paint.color = Colors.black;
135 | paint.shader = SweepGradient(
136 | colors: [
137 | Colors.transparent,
138 | color!,
139 | Colors.transparent,
140 | ],
141 | stops: [
142 | 0.0,
143 | 1.0,
144 | 1.0,
145 | ],
146 | startAngle: math.pi / 8,
147 | endAngle: math.pi / 2,
148 | transform: GradientRotation(math.pi * 2 * progress),
149 | ).createShader(rect);
150 | }
151 | final path = Path.combine(
152 | PathOperation.xor,
153 | Path()..addRect(rect),
154 | Path()..addRect(rect.deflate(4.0)),
155 | );
156 | canvas.drawPath(path, paint);
157 | }
158 |
159 | @override
160 | bool shouldRepaint(_NeonLinePainter oldDelegate) => true;
161 | }
162 |
--------------------------------------------------------------------------------
/lib/animations/neon_button/neon_button_main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'neon_button.dart';
4 |
5 | class NeonButonMain extends StatefulWidget {
6 | @override
7 | NeonButonMainState createState() {
8 | return NeonButonMainState();
9 | }
10 | }
11 |
12 | class NeonButonMainState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | const separator = const SizedBox(
16 | height: 50,
17 | );
18 | return Scaffold(
19 | backgroundColor: Colors.black,
20 | appBar: AppBar(
21 | title: Text("Neon Buttons"),
22 | actions: [
23 | IconButton(
24 | icon: Icon(Icons.refresh),
25 | onPressed: () {
26 | setState(() {});
27 | })
28 | ],
29 | ),
30 | body: Padding(
31 | padding: EdgeInsets.all(5.0),
32 | child: Column(
33 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
34 | children: [
35 | separator,
36 | NeonButton(
37 | text: 'BUTTON SAMPLE BLUE',
38 | color: Colors.blue,
39 | onTap: () {
40 | print('blue pressed');
41 | },
42 | ),
43 | NeonButton(
44 | text: 'BUTTON SAMPLE RED',
45 | color: Colors.red,
46 | onTap: () {
47 | print('red pressed');
48 | },
49 | ),
50 | NeonButton(
51 | text: 'BUTTON SAMPLE GREEN',
52 | color: Colors.green,
53 | onTap: () {
54 | print('green pressed');
55 | },
56 | ),
57 | separator,
58 | ],
59 | ),
60 | ),
61 | );
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/lib/animations/shrink_top_list/shrink_top_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/list_details/character.dart';
3 |
4 | const itemSize = 150.0;
5 |
6 | class ShrinkTopListPage extends StatefulWidget {
7 | @override
8 | _ShrinkTopListPageState createState() => _ShrinkTopListPageState();
9 | }
10 |
11 | class _ShrinkTopListPageState extends State {
12 | final scrollController = ScrollController();
13 |
14 | void onListen() {
15 | setState(() {});
16 | }
17 |
18 | @override
19 | void initState() {
20 | characters.addAll(List.from(characters));
21 | scrollController.addListener(onListen);
22 | super.initState();
23 | }
24 |
25 | @override
26 | void dispose() {
27 | scrollController.removeListener(onListen);
28 | super.dispose();
29 | }
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | return Scaffold(
34 | appBar: AppBar(
35 | title: Text('Shrink top List'),
36 | ),
37 | body: Padding(
38 | padding: const EdgeInsets.only(left: 15.0, right: 15.0, top: 15.0),
39 | child: CustomScrollView(
40 | controller: scrollController,
41 | slivers: [
42 | SliverToBoxAdapter(
43 | child: Placeholder(
44 | fallbackHeight: 100.0,
45 | ),
46 | ),
47 | SliverAppBar(
48 | automaticallyImplyLeading: false,
49 | title: Text(
50 | 'My Characters',
51 | style: TextStyle(color: Colors.black),
52 | ),
53 | pinned: true,
54 | backgroundColor: Colors.transparent,
55 | elevation: 0,
56 | ),
57 | SliverToBoxAdapter(
58 | child: const SizedBox(
59 | height: 50,
60 | ),
61 | ),
62 | SliverList(
63 | delegate: SliverChildBuilderDelegate(
64 | (context, index) {
65 | final heightFactor = 0.6;
66 | final character = characters[index];
67 | final itemPositionOffset = index * itemSize * heightFactor;
68 | final difference =
69 | scrollController.offset - itemPositionOffset;
70 | final percent =
71 | 1.0 - (difference / (itemSize * heightFactor));
72 | double opacity = percent;
73 | double scale = percent;
74 | if (opacity > 1.0) opacity = 1.0;
75 | if (opacity < 0.0) opacity = 0.0;
76 | if (percent > 1.0) scale = 1.0;
77 |
78 | return Align(
79 | heightFactor: heightFactor,
80 | child: Opacity(
81 | opacity: opacity,
82 | child: Transform(
83 | alignment: Alignment.center,
84 | transform: Matrix4.identity()..scale(scale, 1.0),
85 | child: Card(
86 | shape: RoundedRectangleBorder(
87 | borderRadius: BorderRadius.only(
88 | topLeft: Radius.circular(20.0),
89 | topRight: Radius.circular(20.0),
90 | ),
91 | ),
92 | color: Color(character.color!),
93 | child: SizedBox(
94 | height: itemSize,
95 | child: Row(
96 | children: [
97 | Expanded(
98 | child: Padding(
99 | padding: const EdgeInsets.all(15.0),
100 | ),
101 | ),
102 | Image.asset(character.avatar!),
103 | ],
104 | ),
105 | ),
106 | ),
107 | ),
108 | ),
109 | );
110 | },
111 | childCount: characters.length,
112 | ),
113 | ),
114 | ],
115 | ),
116 | ),
117 | );
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/lib/animations/split_widget/main_split_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/animations/split_widget/split_diagonal_widget.dart';
3 |
4 | import 'split_half_widget.dart';
5 |
6 | class MainSplitWidget extends StatelessWidget {
7 | @override
8 | Widget build(BuildContext context) {
9 | return Scaffold(
10 | appBar: AppBar(
11 | title: Text("Split Widget"),
12 | ),
13 | body: Column(
14 | mainAxisAlignment: MainAxisAlignment.center,
15 | crossAxisAlignment: CrossAxisAlignment.stretch,
16 | children: [
17 | Expanded(
18 | child: SplitHalfWidget(
19 | child: Center(
20 | child: Text(
21 | "FLUTTER",
22 | style: Theme.of(context).textTheme.headline3,
23 | ),
24 | ),
25 | ),
26 | ),
27 | Expanded(
28 | child: Container(
29 | color: Colors.grey[500],
30 | child: SplitDiagonalWidget(
31 | child: Image.asset(
32 | "images/dash_dart.png",
33 | fit: BoxFit.fitWidth,
34 | ),
35 | ),
36 | ),
37 | ),
38 | Expanded(
39 | child: Container(
40 | width: MediaQuery.of(context).size.width / 2,
41 | alignment: Alignment.center,
42 | color: Colors.grey[300],
43 | child: SplitHalfWidget(
44 | child: FlutterLogo(
45 | size: MediaQuery.of(context).size.width / 3,
46 | ),
47 | ),
48 | ),
49 | ),
50 | ],
51 | ),
52 | );
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/animations/split_widget/split_diagonal_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SplitDiagonalWidget extends StatefulWidget {
4 | final Widget child;
5 |
6 | const SplitDiagonalWidget({
7 | Key? key,
8 | required this.child,
9 | }) : super(key: key);
10 |
11 | @override
12 | _SplitDiagonalWidgetState createState() => _SplitDiagonalWidgetState();
13 | }
14 |
15 | class _SplitDiagonalWidgetState extends State
16 | with SingleTickerProviderStateMixin {
17 | late AnimationController _controller;
18 | late Animation _animation;
19 | double? _childHeight;
20 | GlobalKey _childKey = GlobalKey();
21 |
22 | Widget _buildSide({bool top = true}) {
23 | return AnimatedBuilder(
24 | animation: _animation,
25 | builder: (_, child) => Transform.translate(
26 | offset: Offset(0.0, !top ? 1 : -1) * _animation.value / 2,
27 | child: child,
28 | ),
29 | child: ClipPath(
30 | child: widget.child,
31 | clipper: SplitClipper(top: top),
32 | ),
33 | );
34 | }
35 |
36 | void _onLayoutDone(_) {
37 | _childHeight = _childKey.currentContext!.size!.height;
38 | _animation = Tween(
39 | begin: 0.0,
40 | end: _childHeight! * 0.5,
41 | ).animate(
42 | CurvedAnimation(
43 | parent: _controller,
44 | curve: Curves.decelerate,
45 | ),
46 | );
47 | setState(() {});
48 | }
49 |
50 | @override
51 | void initState() {
52 | _controller = AnimationController(
53 | vsync: this,
54 | duration: Duration(seconds: 1),
55 | );
56 |
57 | WidgetsBinding.instance!.addPostFrameCallback(_onLayoutDone);
58 | super.initState();
59 | }
60 |
61 | void _startAnimation() {
62 | _controller.forward(from: 0.0).whenComplete(() => _controller.reverse());
63 | }
64 |
65 | @override
66 | Widget build(BuildContext context) {
67 | return GestureDetector(
68 | onTap: _startAnimation,
69 | key: _childKey,
70 | child: Center(
71 | child: SizedBox(
72 | height: _childHeight != null ? _childHeight : 0.0,
73 | width: MediaQuery.of(context).size.width,
74 | child: _childHeight != null
75 | ? Stack(
76 | fit: StackFit.expand,
77 | children: [
78 | _buildSide(),
79 | _buildSide(top: false),
80 | ],
81 | )
82 | : const SizedBox.shrink(),
83 | ),
84 | ),
85 | );
86 | }
87 | }
88 |
89 | class SplitClipper extends CustomClipper {
90 | final bool top;
91 |
92 | SplitClipper({this.top = false});
93 |
94 | @override
95 | Path getClip(Size size) {
96 | Path path = Path();
97 | path.moveTo(0.0, size.height * 0.75);
98 | path.lineTo(size.width, size.height * 0.25);
99 | if (!top) {
100 | path.lineTo(size.width, size.height);
101 | path.lineTo(0.0, size.height);
102 | } else {
103 | path.lineTo(size.width, 0.0);
104 | path.lineTo(0.0, 0.0);
105 | }
106 |
107 | path.close();
108 | return path;
109 | }
110 |
111 | @override
112 | bool shouldReclip(CustomClipper oldClipper) => false;
113 | }
114 |
--------------------------------------------------------------------------------
/lib/animations/split_widget/split_half_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SplitHalfWidget extends StatefulWidget {
4 | final Widget child;
5 |
6 | const SplitHalfWidget({
7 | Key? key,
8 | required this.child,
9 | }) : super(key: key);
10 |
11 | @override
12 | _SplitHalfWidgetState createState() => _SplitHalfWidgetState();
13 | }
14 |
15 | class _SplitHalfWidgetState extends State
16 | with SingleTickerProviderStateMixin {
17 | late AnimationController _controller;
18 | late Animation _animation;
19 | double? _childWidth;
20 | GlobalKey _childKey = GlobalKey();
21 |
22 | Widget _buildSide({bool left = true}) {
23 | return _childWidth != null
24 | ? AnimatedBuilder(
25 | animation: _animation,
26 | builder: (_, child) => SizedBox(
27 | width: _childWidth,
28 | child: Transform.translate(
29 | offset: Offset((left ? 1 : -1) * _animation.value / 2, 0.0),
30 | child: child,
31 | ),
32 | ),
33 | child: ClipPath(
34 | child: widget.child,
35 | clipper: SplitClipper(left: left),
36 | ),
37 | )
38 | : SizedBox.shrink();
39 | }
40 |
41 | void _onLayoutDone(_) {
42 | _childWidth = _childKey.currentContext!.size!.width / 2;
43 | _animation = Tween(
44 | begin: _childWidth,
45 | end: 0.0,
46 | ).animate(
47 | CurvedAnimation(
48 | parent: _controller,
49 | curve: Curves.decelerate,
50 | ),
51 | );
52 | setState(() {});
53 | }
54 |
55 | @override
56 | void initState() {
57 | _controller = AnimationController(
58 | vsync: this,
59 | duration: Duration(seconds: 1),
60 | );
61 |
62 | WidgetsBinding.instance!.addPostFrameCallback(_onLayoutDone);
63 | super.initState();
64 | }
65 |
66 | void _startAnimation() {
67 | _controller.forward(from: 0.0).whenComplete(() => _controller.reverse());
68 | }
69 |
70 | @override
71 | Widget build(BuildContext context) {
72 | return GestureDetector(
73 | onTap: _startAnimation,
74 | child: Row(
75 | key: _childKey,
76 | mainAxisAlignment: MainAxisAlignment.center,
77 | children: [
78 | _buildSide(),
79 | _buildSide(left: false),
80 | ],
81 | ),
82 | );
83 | }
84 | }
85 |
86 | class SplitClipper extends CustomClipper {
87 | final bool left;
88 |
89 | SplitClipper({this.left = false});
90 |
91 | @override
92 | Path getClip(Size size) {
93 | Path path = Path();
94 | if (!left) {
95 | path.addRect(
96 | Rect.fromLTWH(size.width / 2, 0.0, size.width / 2, size.height));
97 | } else {
98 | path.addRect(Rect.fromLTWH(0.0, 0.0, size.width / 2, size.height));
99 | }
100 |
101 | path.close();
102 | return path;
103 | }
104 |
105 | @override
106 | bool shouldReclip(CustomClipper oldClipper) => false;
107 | }
108 |
--------------------------------------------------------------------------------
/lib/animations/turn_on_the_light/turn_on_the_light.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class TurnOnTheLight extends StatefulWidget {
4 | @override
5 | _TurnOnTheLightState createState() => _TurnOnTheLightState();
6 | }
7 |
8 | class _TurnOnTheLightState extends State {
9 | double x = 0, y = 0;
10 | final radius = 60.0;
11 | bool lightOn = false;
12 |
13 | void _onPanUpdate(Offset offset) {
14 | setState(() {
15 | lightOn = true;
16 | x = offset.dx;
17 | y = offset.dy;
18 | });
19 | }
20 |
21 | void _onPanEnd(_) {
22 | setState(() {
23 | lightOn = false;
24 | });
25 | }
26 |
27 | @override
28 | Widget build(BuildContext context) {
29 | return Scaffold(
30 | appBar: AppBar(
31 | title: Text("Turn on the light"),
32 | ),
33 | body: GestureDetector(
34 | onPanStart: (val) => _onPanUpdate(val.localPosition),
35 | onPanUpdate: (val) => _onPanUpdate(val.localPosition),
36 | onPanEnd: _onPanEnd,
37 | child: Stack(
38 | fit: StackFit.expand,
39 | children: [
40 | Center(
41 | child: FlutterLogo(
42 | size: MediaQuery.of(context).size.width,
43 | style: FlutterLogoStyle.horizontal,
44 | ),
45 | ),
46 | ClipPath(
47 | clipper: lightOn ? LightClipper(x, y, radius: radius) : null,
48 | child: Container(
49 | color: Colors.black,
50 | ),
51 | ),
52 | Positioned(
53 | bottom: 0,
54 | left: 0,
55 | right: 0,
56 | child: Padding(
57 | padding: const EdgeInsets.all(15.0),
58 | child: Text(
59 | "Touch the screen to turn on the light",
60 | textAlign: TextAlign.center,
61 | style: TextStyle(
62 | color: Colors.white,
63 | ),
64 | ),
65 | ),
66 | ),
67 | ],
68 | ),
69 | ),
70 | );
71 | }
72 | }
73 |
74 | class LightClipper extends CustomClipper {
75 | final double x, y;
76 | final radius;
77 | LightClipper(this.x, this.y, {this.radius = 50.0});
78 |
79 | @override
80 | Path getClip(Size size) {
81 | final circlePath = Path()
82 | ..addOval(Rect.fromCircle(center: Offset(x, y), radius: radius));
83 | final fullPath = Path()
84 | ..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
85 | return Path.combine(PathOperation.reverseDifference, circlePath, fullPath);
86 | }
87 |
88 | @override
89 | bool shouldReclip(LightClipper oldClipper) =>
90 | x != oldClipper.x || y != oldClipper.y;
91 | }
92 |
--------------------------------------------------------------------------------
/lib/app_clone/album_flow/album.dart:
--------------------------------------------------------------------------------
1 | class Album {
2 | final String? image;
3 |
4 | const Album._(this.image);
5 |
6 | factory Album.fromJson(dynamic json) =>
7 | Album._(((json['image'] as List).last)['#text']);
8 | }
9 |
10 | const albumsData = [
11 | Album._(
12 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/ac6921b5afdc64f859a2aa38773a468b.jpg'),
13 | Album._(
14 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/cf3a46415a1f4e9cce0f365af8225097.png'),
15 | Album._(
16 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/1e5ef1165e904436a5a244c936fb505c.png'),
17 | Album._(
18 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/716e62c7152a4788bb47cfe7207b8521.jpg'),
19 | Album._(
20 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/cf47afa9760249238e3269e61b5facb4.png'),
21 | Album._(
22 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/cdee664c355c4c9dbb0e7ba8db690064.png'),
23 | Album._(
24 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/05cc536929ca130183b15c1f1f9f221e.jpg'),
25 | Album._(
26 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/cc8218235b6f438dbddd294d9022880e.png'),
27 | Album._(
28 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/667c311baea63b88f110ad49e094fd12.jpg'),
29 | Album._(
30 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/c1e96f217c4c4d15a6d00fff66e21226.png'),
31 | Album._(
32 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/16849a85994fe7b931dd348c5fb70987.jpg'),
33 | Album._(
34 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/ba2bc55a13cc4dd9824ef9ebb8f468f0.jpg'),
35 | Album._(
36 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/e588abb451e854488dfe2a64a6e0aeb5.jpg'),
37 | Album._(
38 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/b788451ab3594c81b77ff24e6f5d439f.png'),
39 | Album._(
40 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/05442cefecfc46b4aeb6ea62a5366a5e.jpg'),
41 | Album._(
42 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/1a77ce6d579b4ba5b0c5caa9a4606cf6.png'),
43 | Album._(
44 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/bc4e31504f5f47adb31f36aa0889be45.png'),
45 | Album._(
46 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/742e40bd3aa5e14e86842f457d7ece2c.jpg'),
47 | Album._(
48 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/89c670accaa20ceab8f53f5dced75706.jpg'),
49 | Album._(
50 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/6d305843325cec758562218fa504d47e.png'),
51 | Album._(
52 | 'https:\/\/lastfm.freetls.fastly.net\/i\/u\/174s\/66cf5a401c274f418e0c35268931d6ee.png'),
53 | ];
54 |
--------------------------------------------------------------------------------
/lib/app_clone/album_flow/album_flow_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'album_image.dart';
4 |
5 | const _itemCounts = 20;
6 |
7 | class AlbumFlowDetailPage extends StatelessWidget {
8 | final String? image;
9 | final double? angle;
10 |
11 | const AlbumFlowDetailPage({
12 | Key? key,
13 | this.image,
14 | this.angle,
15 | }) : super(key: key);
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | final size = MediaQuery.of(context).size;
20 | final imageSize = size.width * 0.7;
21 | final margin = 20.0;
22 | return SafeArea(
23 | child: Scaffold(
24 | backgroundColor: Colors.black,
25 | body: Stack(
26 | children: [
27 | Positioned.fill(
28 | left: margin / 2,
29 | right: margin / 2,
30 | top: imageSize - margin,
31 | bottom: 0.0,
32 | child: Card(
33 | color: Colors.white,
34 | shape: RoundedRectangleBorder(
35 | borderRadius: BorderRadius.only(
36 | topLeft: Radius.circular(25),
37 | topRight: Radius.circular(25),
38 | ),
39 | ),
40 | child: ListView.builder(
41 | padding: const EdgeInsets.only(top: 40),
42 | itemCount: _itemCounts,
43 | itemBuilder: (context, index) {
44 | return Padding(
45 | padding: const EdgeInsets.symmetric(
46 | horizontal: 15.0, vertical: 5.0),
47 | child: ListTile(
48 | title: Text(
49 | 'Random Song ${index + 1}',
50 | style: TextStyle(
51 | fontWeight: FontWeight.w700,
52 | fontSize: 18,
53 | ),
54 | ),
55 | trailing: Text('3:33'),
56 | ),
57 | );
58 | },
59 | ),
60 | ),
61 | ),
62 | Positioned(
63 | width: imageSize,
64 | height: imageSize,
65 | top: 50,
66 | left: (size.width - imageSize) / 2,
67 | child: AlbumImage(
68 | image: image,
69 | angle: angle,
70 | ),
71 | ),
72 | Positioned(
73 | left: margin,
74 | top: margin,
75 | child: BackButton(
76 | color: Colors.white,
77 | ),
78 | ),
79 | ],
80 | ),
81 | ),
82 | );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/app_clone/album_flow/album_image.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:cached_network_image/cached_network_image.dart';
4 | import 'package:vector_math/vector_math.dart' as vector;
5 |
6 | class AlbumImage extends StatelessWidget {
7 | final String? image;
8 | final double? angle;
9 |
10 | const AlbumImage({
11 | Key? key,
12 | required this.image,
13 | this.angle,
14 | }) : super(key: key);
15 |
16 | @override
17 | Widget build(BuildContext context) {
18 | return Hero(
19 | tag: image!,
20 | flightShuttleBuilder: (
21 | _,
22 | Animation animation,
23 | HeroFlightDirection flightDirection,
24 | BuildContext fromHeroContext,
25 | BuildContext toHeroContext,
26 | ) {
27 | final Hero toHero = toHeroContext.widget as Hero;
28 | final Hero fromHero = fromHeroContext.widget as Hero;
29 | return AnimatedBuilder(
30 | animation: animation,
31 | child: flightDirection == HeroFlightDirection.push
32 | ? toHero.child
33 | : fromHero.child,
34 | builder: (context, child) {
35 | double? newValue = 0.0;
36 | if (flightDirection == HeroFlightDirection.push) {
37 | newValue = lerpDouble((360.0 - angle!.abs()), 0, animation.value);
38 | } else {
39 | newValue = lerpDouble(
40 | 0, (angle!.abs() - 360).abs(), 1 - animation.value);
41 | }
42 | return Transform(
43 | alignment: Alignment.topCenter,
44 | transform: Matrix4.identity()
45 | ..setEntry(3, 2, 0.002)
46 | ..rotateX(vector.radians(newValue!)),
47 | child: child,
48 | );
49 | },
50 | );
51 | },
52 | child: Card(
53 | color: Colors.black,
54 | clipBehavior: Clip.hardEdge,
55 | shape: RoundedRectangleBorder(
56 | borderRadius: BorderRadius.circular(15.0),
57 | ),
58 | elevation: 10,
59 | child: CachedNetworkImage(
60 | imageUrl: image!,
61 | fit: BoxFit.cover,
62 | placeholder: (context, url) =>
63 | Center(child: CircularProgressIndicator()),
64 | ),
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/app_clone/android_messages/android_messages_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class AndroidMessagesPage extends StatefulWidget {
4 | @override
5 | _AndroidMessagesPageState createState() => _AndroidMessagesPageState();
6 | }
7 |
8 | class _AndroidMessagesPageState extends State {
9 | bool isGoingDown = true;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Theme(
14 | data: ThemeData.dark(),
15 | child: Scaffold(
16 | appBar: AppBar(
17 | elevation: 0.0,
18 | centerTitle: true,
19 | backgroundColor: Colors.transparent,
20 | title: Text("Messages"),
21 | actions: [
22 | IconButton(
23 | icon: Icon(Icons.search),
24 | onPressed: () => null,
25 | ),
26 | IconButton(
27 | icon: Icon(Icons.more_vert),
28 | onPressed: () => null,
29 | ),
30 | ],
31 | ),
32 | body: NotificationListener(
33 | onNotification: (onScrollNotification) {
34 | if (onScrollNotification is ScrollUpdateNotification) {
35 | if (onScrollNotification.scrollDelta! <= 0.0) {
36 | if (!isGoingDown) setState(() => isGoingDown = true);
37 | } else {
38 | if (isGoingDown) setState(() => isGoingDown = false);
39 | }
40 | }
41 | return false;
42 | },
43 | child: _buildList()),
44 | floatingActionButton: MyFabButton(isGoingDown)),
45 | );
46 | }
47 |
48 | _buildList() {
49 | return ListView(
50 | physics: ClampingScrollPhysics(),
51 | children: List.generate(30, (index) => "Message ${index + 1}")
52 | .map((val) => SMSItem(
53 | number: "456",
54 | text: val,
55 | ))
56 | .toList(),
57 | );
58 | }
59 | }
60 |
61 | class MyFabButton extends StatelessWidget {
62 | final bool isExtended;
63 |
64 | MyFabButton(this.isExtended);
65 |
66 | @override
67 | Widget build(BuildContext context) {
68 | return AnimatedContainer(
69 | duration: Duration(milliseconds: 400),
70 | curve: Curves.easeInOut,
71 | child: RawMaterialButton(
72 | elevation: 5.0,
73 | shape: isExtended
74 | ? RoundedRectangleBorder(
75 | borderRadius: BorderRadius.all(Radius.circular(25.0)))
76 | : CircleBorder(),
77 | onPressed: () => null,
78 | fillColor: Colors.blue[600],
79 | child: Padding(
80 | padding: const EdgeInsets.all(12.0),
81 | child: isExtended
82 | ? Row(
83 | mainAxisSize: MainAxisSize.min,
84 | children: [
85 | const Icon(
86 | Icons.message,
87 | color: Colors.white,
88 | ),
89 | SizedBox(
90 | width: 5.0,
91 | ),
92 | Text(
93 | "Start chat",
94 | style: TextStyle(color: Colors.white),
95 | )
96 | ],
97 | )
98 | : const Icon(
99 | Icons.message,
100 | color: Colors.white,
101 | ),
102 | )));
103 | }
104 | }
105 |
106 | class SMSItem extends StatelessWidget {
107 | final String? number;
108 | final String? text;
109 |
110 | SMSItem({this.number, this.text});
111 |
112 | @override
113 | Widget build(BuildContext context) {
114 | return Padding(
115 | padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 10.0),
116 | child: Row(
117 | children: [
118 | CircleAvatar(
119 | child: Icon(Icons.person),
120 | backgroundColor: Colors.redAccent[400],
121 | ),
122 | Expanded(
123 | child: Padding(
124 | padding: const EdgeInsets.symmetric(horizontal: 15.0),
125 | child: Column(
126 | crossAxisAlignment: CrossAxisAlignment.start,
127 | children: [
128 | Text(
129 | number!,
130 | textAlign: TextAlign.left,
131 | style: TextStyle(fontSize: 17.0),
132 | ),
133 | Text(
134 | text!,
135 | textAlign: TextAlign.left,
136 | style: TextStyle(fontSize: 15.0, color: Colors.grey),
137 | )
138 | ],
139 | ),
140 | ),
141 | ),
142 | Align(
143 | alignment: Alignment.topRight,
144 | child: Text(
145 | "Sat",
146 | style: TextStyle(fontSize: 15.0, color: Colors.grey),
147 | ),
148 | )
149 | ],
150 | ),
151 | );
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/lib/app_clone/credit_cards_concept/credit_card.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/widgets.dart';
4 |
5 | class CreditCard {
6 | final Color? color;
7 | final String? number;
8 | final String? ccv;
9 | final double? amount;
10 |
11 | CreditCard({
12 | this.color,
13 | this.number,
14 | this.ccv,
15 | this.amount,
16 | });
17 | }
18 |
19 | final Random random = new Random();
20 |
21 | double doubleInRange(Random source, int start, int end) =>
22 | source.nextDouble() * (end - start) + start;
23 |
24 | int _intInRange(Random source, int start, int end) =>
25 | start + source.nextInt(end - start);
26 |
27 | String _getFourNumbers() => _intInRange(random, 1000, 9999).toString();
28 |
29 | final creditCards = List.generate(
30 | 20,
31 | (index) => CreditCard(
32 | amount: doubleInRange(random, 500, 20000),
33 | ccv: _getFourNumbers(),
34 | color: Colors.primaries[index % Colors.primaries.length],
35 | number:
36 | "${_getFourNumbers()} ${_getFourNumbers()} ${_getFourNumbers()} ${_getFourNumbers()}",
37 | ),
38 | );
39 |
--------------------------------------------------------------------------------
/lib/app_clone/credit_cards_concept/credit_cards_concept_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_samples/app_clone/credit_cards_concept/credit_card.dart';
5 | import 'package:flutter_samples/app_clone/credit_cards_concept/credit_card_widget.dart';
6 |
7 | class CreditCardsConceptDetailPage extends StatelessWidget {
8 | final CreditCard? card;
9 |
10 | const CreditCardsConceptDetailPage({Key? key, this.card}) : super(key: key);
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | final textTheme = Theme.of(context).textTheme;
15 | return Theme(
16 | data: ThemeData.dark().copyWith(
17 | backgroundColor: Colors.black,
18 | scaffoldBackgroundColor: Colors.black,
19 | ),
20 | child: Scaffold(
21 | body: Padding(
22 | padding: const EdgeInsets.all(0.0),
23 | child: Column(
24 | crossAxisAlignment: CrossAxisAlignment.stretch,
25 | children: [
26 | AppBar(
27 | elevation: 0,
28 | backgroundColor: Colors.transparent,
29 | ),
30 | Expanded(
31 | child: CustomScrollView(
32 | slivers: [
33 | SliverList(
34 | delegate: SliverChildListDelegate(
35 | [
36 | Text(
37 | 'Full card',
38 | textAlign: TextAlign.center,
39 | style: textTheme.headline6!.copyWith(
40 | color: Colors.white,
41 | ),
42 | ),
43 | const SizedBox(
44 | height: 10,
45 | ),
46 | Text(
47 | 'Rotable the card to view the security code',
48 | textAlign: TextAlign.center,
49 | style: textTheme.subtitle2!.copyWith(
50 | color: Colors.grey[400],
51 | ),
52 | ),
53 | const SizedBox(
54 | height: 60,
55 | ),
56 | ],
57 | ),
58 | ),
59 | SliverPersistentHeader(
60 | pinned: true,
61 | delegate: MyCardHeaderDelegate(card, 170.0),
62 | ),
63 | SliverToBoxAdapter(
64 | child: Padding(
65 | padding: const EdgeInsets.only(left: 20.0, top: 25.0),
66 | child: Text(
67 | 'Today',
68 | textAlign: TextAlign.left,
69 | style: textTheme.headline6!.copyWith(
70 | color: Colors.white,
71 | ),
72 | ),
73 | ),
74 | ),
75 | SliverList(
76 | delegate: SliverChildBuilderDelegate(
77 | (context, index) {
78 | return MovementWidget(
79 | index: index,
80 | );
81 | },
82 | childCount: 25,
83 | ),
84 | ),
85 | ],
86 | ),
87 | ),
88 | ],
89 | ),
90 | ),
91 | ),
92 | );
93 | }
94 | }
95 |
96 | class MyCardHeaderDelegate extends SliverPersistentHeaderDelegate {
97 | final CreditCard? card;
98 | final double height;
99 |
100 | MyCardHeaderDelegate(
101 | this.card,
102 | this.height,
103 | );
104 |
105 | @override
106 | Widget build(
107 | BuildContext context, double shrinkOffset, bool overlapsContent) {
108 | return Container(
109 | decoration: BoxDecoration(
110 | gradient: LinearGradient(
111 | begin: Alignment.topCenter,
112 | end: Alignment.bottomCenter,
113 | colors: [
114 | Colors.black,
115 | Colors.black87,
116 | ],
117 | ),
118 | ),
119 | padding: const EdgeInsets.symmetric(horizontal: 25),
120 | child: CreditCardWidget(
121 | card: card,
122 | isDetail: true,
123 | ),
124 | );
125 | }
126 |
127 | @override
128 | double get maxExtent => height;
129 |
130 | @override
131 | double get minExtent => height;
132 |
133 | @override
134 | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false;
135 | }
136 |
137 | const categories = ['Shoes', 'Food', 'Restaurant', 'Hotel'];
138 | final random = Random();
139 |
140 | class MovementWidget extends StatelessWidget {
141 | final int? index;
142 |
143 | const MovementWidget({Key? key, this.index}) : super(key: key);
144 |
145 | @override
146 | Widget build(BuildContext context) {
147 | return ListTile(
148 | title: Text(
149 | "Movement ${index! + 1}",
150 | style: TextStyle(
151 | fontWeight: FontWeight.bold,
152 | ),
153 | ),
154 | subtitle: Text(
155 | categories[index! % categories.length],
156 | style: TextStyle(
157 | color: Colors.grey,
158 | ),
159 | ),
160 | leading: CircleAvatar(
161 | backgroundColor: Colors.primaries[index! % Colors.primaries.length],
162 | ),
163 | trailing: Text(
164 | doubleInRange(random, 1, 5000).toStringAsFixed(2),
165 | style: TextStyle(
166 | fontWeight: FontWeight.bold,
167 | ),
168 | ),
169 | );
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/lib/app_clone/credit_cards_concept/credit_cards_concept_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/app_clone/credit_cards_concept/credit_card.dart';
3 | import 'package:flutter_samples/app_clone/credit_cards_concept/credit_cards_concept_detail_page.dart';
4 | import 'credit_card_widget.dart';
5 |
6 | //ignore: must_be_immutable
7 | class CreditCardConceptPage extends StatelessWidget {
8 | final pageNotifier = ValueNotifier(0);
9 | int _lastPage = 0;
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | final textTheme = Theme.of(context).textTheme;
14 | const padding = EdgeInsets.all(18.0);
15 | return Theme(
16 | data: ThemeData.dark().copyWith(
17 | backgroundColor: Colors.black,
18 | scaffoldBackgroundColor: Colors.black,
19 | ),
20 | child: Scaffold(
21 | appBar: AppBar(
22 | elevation: 0,
23 | backgroundColor: Colors.transparent,
24 | ),
25 | body: Column(
26 | crossAxisAlignment: CrossAxisAlignment.stretch,
27 | children: [
28 | Padding(
29 | padding: padding,
30 | child: Column(
31 | crossAxisAlignment: CrossAxisAlignment.start,
32 | children: [
33 | Text(
34 | 'Bank Cards',
35 | style: textTheme.headline4!.copyWith(
36 | color: Colors.white,
37 | fontWeight: FontWeight.bold,
38 | ),
39 | ),
40 | const SizedBox(height: 20),
41 | Text(
42 | 'Balance',
43 | style: textTheme.subtitle2!.copyWith(
44 | color: Colors.grey,
45 | ),
46 | ),
47 | const SizedBox(height: 3),
48 | ValueListenableBuilder(
49 | valueListenable: pageNotifier,
50 | builder: (context, snapshot, _) {
51 | final currentCard = creditCards[snapshot];
52 | final lastCard = creditCards[_lastPage];
53 | return TweenAnimationBuilder(
54 | tween: Tween(
55 | begin: lastCard.amount,
56 | end: currentCard.amount,
57 | ),
58 | duration: const Duration(milliseconds: 500),
59 | builder: (_, value, ___) => Text(
60 | value.toStringAsFixed(2),
61 | style: textTheme.headline6!.copyWith(
62 | color: Colors.white,
63 | fontWeight: FontWeight.bold,
64 | ),
65 | ),
66 | );
67 | }),
68 | ],
69 | ),
70 | ),
71 | Expanded(
72 | child: PageView.builder(
73 | scrollDirection: Axis.horizontal,
74 | onPageChanged: (page) {
75 | _lastPage = pageNotifier.value;
76 | pageNotifier.value = page;
77 | },
78 | controller: PageController(
79 | viewportFraction: 0.7,
80 | ),
81 | physics: const BouncingScrollPhysics(),
82 | itemCount: creditCards.length,
83 | itemBuilder: (_, index) => Align(
84 | child: Transform.translate(
85 | offset: Offset(-30.0, 0.0),
86 | child: Padding(
87 | padding: const EdgeInsets.all(15.0),
88 | child: CreditCardWidget(
89 | onTap: () {
90 | final page = CreditCardsConceptDetailPage(
91 | card: creditCards[index],
92 | );
93 | Navigator.of(context).push(
94 | PageRouteBuilder(
95 | pageBuilder: (BuildContext context,
96 | Animation animation, _) {
97 | return FadeTransition(
98 | opacity: animation,
99 | child: page,
100 | );
101 | },
102 | transitionDuration: Duration(milliseconds: 900),
103 | ),
104 | );
105 | },
106 | card: creditCards[index],
107 | ),
108 | ),
109 | ),
110 | ),
111 | ),
112 | ),
113 | const SizedBox(
114 | height: 35,
115 | ),
116 | ],
117 | ),
118 | ),
119 | );
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/lib/app_clone/main_apps_clone.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/app_clone/album_flow/album_flow_page.dart';
3 | import 'package:flutter_samples/app_clone/android_messages/android_messages_page.dart';
4 | import 'package:flutter_samples/app_clone/credit_cards_concept/credit_cards_concept_page.dart';
5 | import 'package:flutter_samples/app_clone/movies_concept/movies_concept_page.dart';
6 | import 'package:flutter_samples/app_clone/photo_concept/photo_concept_page.dart';
7 | import 'package:flutter_samples/app_clone/shoes_store/shoes_store_page.dart';
8 | import 'package:flutter_samples/app_clone/sports_store/sports_store_page.dart';
9 | import 'package:flutter_samples/app_clone/travel_concept/travel_concept_page.dart';
10 | import 'package:flutter_samples/app_clone/twitter_profile/twitter_profile_page.dart';
11 | import 'package:flutter_samples/main.dart';
12 |
13 | class MainAppsClone extends StatefulWidget {
14 | @override
15 | MainAppCloneState createState() {
16 | return new MainAppCloneState();
17 | }
18 | }
19 |
20 | class MainAppCloneState extends State {
21 | onButtonTap(Widget page) {
22 | Navigator.push(
23 | context, MaterialPageRoute(builder: (BuildContext context) => page));
24 | }
25 |
26 | @override
27 | Widget build(BuildContext context) {
28 | return Scaffold(
29 | appBar: AppBar(
30 | title: Text("Flutter Apps Clone"),
31 | ),
32 | body: Padding(
33 | padding: EdgeInsets.all(15.0),
34 | child: ListView(
35 | children: [
36 | MyMenuButton(
37 | title: "Android Messages Page",
38 | actionTap: () {
39 | onButtonTap(AndroidMessagesPage());
40 | },
41 | ),
42 | MyMenuButton(
43 | title: "Twitter Profile Page",
44 | actionTap: () {
45 | onButtonTap(TwitterProfilePage());
46 | },
47 | ),
48 | MyMenuButton(
49 | title: "Movies Concept",
50 | actionTap: () {
51 | onButtonTap(MoviesConceptPage());
52 | },
53 | ),
54 | MyMenuButton(
55 | title: "Photo Concept",
56 | actionTap: () {
57 | onButtonTap(PhotoConceptPage());
58 | },
59 | ),
60 | MyMenuButton(
61 | title: "Sports Store",
62 | actionTap: () {
63 | onButtonTap(SportsStorePage());
64 | },
65 | ),
66 | MyMenuButton(
67 | title: "Shoes Store",
68 | actionTap: () {
69 | onButtonTap(ShoesStorePage());
70 | },
71 | ),
72 | MyMenuButton(
73 | title: "Album Flow",
74 | actionTap: () {
75 | onButtonTap(AlbumFlowPage());
76 | },
77 | ),
78 | MyMenuButton(
79 | title: "Credit Cards Concept",
80 | actionTap: () {
81 | onButtonTap(CreditCardConceptPage());
82 | },
83 | ),
84 | MyMenuButton(
85 | title: "Travel Concept",
86 | actionTap: () {
87 | onButtonTap(TravelConceptPage());
88 | },
89 | ),
90 | ],
91 | ),
92 | ),
93 | );
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/lib/app_clone/photo_concept/photo_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class PhotoDetailPage extends StatelessWidget {
4 | final String? image;
5 | final String? tag;
6 |
7 | const PhotoDetailPage({Key? key, this.image, this.tag}) : super(key: key);
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | return Scaffold(
12 | backgroundColor: Colors.black,
13 | body: Padding(
14 | padding: const EdgeInsets.all(18.0),
15 | child: Column(
16 | children: [
17 | Align(
18 | alignment: Alignment.topLeft,
19 | child: Padding(
20 | padding: const EdgeInsets.all(8.0),
21 | child: BackButton(
22 | color: Colors.white,
23 | ),
24 | ),
25 | ),
26 | Center(
27 | child: Hero(
28 | tag: tag!,
29 | child: Image.network(
30 | image!,
31 | fit: BoxFit.cover,
32 | ),
33 | ),
34 | ),
35 | ],
36 | ),
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/app_clone/shoes_store/shoes_store_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import 'shoes_store_page.dart';
4 |
5 | class ShoesStoreDetailPage extends StatelessWidget {
6 | final Shoe? shoe;
7 |
8 | const ShoesStoreDetailPage({Key? key, this.shoe}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | final size = MediaQuery.of(context).size;
13 | return Scaffold(
14 | body: Stack(
15 | fit: StackFit.expand,
16 | children: [
17 | Positioned(
18 | top: -size.width / 2,
19 | right: -size.width / 3,
20 | width: size.width * 1.4,
21 | height: size.width * 1.4,
22 | child: Hero(
23 | tag: 'hero_background_${shoe!.name}',
24 | child: Container(
25 | decoration: BoxDecoration(
26 | color: shoe!.color,
27 | shape: BoxShape.circle,
28 | ),
29 | ),
30 | ),
31 | ),
32 | Align(
33 | alignment: Alignment.topCenter,
34 | child: SizedBox(
35 | height: kToolbarHeight + 20,
36 | child: AppBar(
37 | backgroundColor: Colors.transparent,
38 | elevation: 0,
39 | title: Text(
40 | shoe!.name!.split(' ').first,
41 | style: TextStyle(
42 | color: Colors.white,
43 | fontSize: 25,
44 | fontWeight: FontWeight.w700),
45 | ),
46 | actions: [
47 | Padding(
48 | padding: const EdgeInsets.only(right: 14.0),
49 | child: Material(
50 | elevation: 10,
51 | shape: CircleBorder(
52 | side: BorderSide(
53 | color: shoe!.color!,
54 | )),
55 | color: shoe!.color,
56 | child: Padding(
57 | padding: const EdgeInsets.all(5.0),
58 | child: Icon(Icons.favorite_border),
59 | ),
60 | ),
61 | ),
62 | ]),
63 | )),
64 | Align(
65 | alignment: Alignment.topCenter,
66 | child: Padding(
67 | padding: EdgeInsets.only(top: size.height * 0.1),
68 | child: Hero(
69 | tag: 'hero_image_${shoe!.name}',
70 | child: Image.asset(
71 | shoe!.image!,
72 | height: MediaQuery.of(context).size.width / 1.2,
73 | ),
74 | ),
75 | ),
76 | ),
77 | ],
78 | ),
79 | );
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/app_clone/sports_store/sports_store_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/app_clone/sports_store/sports_store_page.dart';
3 |
4 | class SportsStoreDetailPage extends StatelessWidget {
5 | final Ball? ball;
6 |
7 | const SportsStoreDetailPage({Key? key, this.ball}) : super(key: key);
8 |
9 | @override
10 | Widget build(BuildContext context) {
11 | final size = MediaQuery.of(context).size;
12 | return Theme(
13 | data: ThemeData.light(),
14 | child: Scaffold(
15 | body: Stack(
16 | fit: StackFit.expand,
17 | children: [
18 | Positioned(
19 | top: 0,
20 | right: 0,
21 | width: size.width / 2.5,
22 | height: size.height / 1.8,
23 | child: Hero(
24 | tag: 'hero_background_${ball!.name}',
25 | child: Container(
26 | decoration: BoxDecoration(
27 | color: ball!.color,
28 | borderRadius: BorderRadius.only(
29 | bottomLeft: Radius.circular(30),
30 | ),
31 | ),
32 | ),
33 | ),
34 | ),
35 | Positioned(
36 | left: 30,
37 | top: 100,
38 | child: Hero(
39 | tag: 'hero_text_${ball!.name}',
40 | child: Material(
41 | color: Colors.transparent,
42 | child: Text(
43 | ball!.name!.split(' ').join('\n'),
44 | style: TextStyle(
45 | color: Colors.black,
46 | fontSize: 40,
47 | fontWeight: FontWeight.w700),
48 | ),
49 | ),
50 | ),
51 | ),
52 | Positioned(
53 | right: 30,
54 | top: size.height / 4,
55 | child: Hero(
56 | tag: 'hero_ball_${ball!.name}',
57 | child: Image.asset(
58 | ball!.image!,
59 | height: MediaQuery.of(context).size.width / 2.2,
60 | ),
61 | ),
62 | ),
63 | Positioned(
64 | left: 20,
65 | top: 40,
66 | child: BackButton(),
67 | ),
68 | ],
69 | ),
70 | ),
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/lib/app_clone/travel_concept/travel_concept_detail_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/app_clone/travel_concept/travel_concept_page.dart';
3 |
4 | class TravelConceptDetailPage extends StatelessWidget {
5 | final LocationCard? location;
6 |
7 | const TravelConceptDetailPage({Key? key, this.location}) : super(key: key);
8 |
9 | void _onVerticalDrag(
10 | DragUpdateDetails details,
11 | BuildContext context,
12 | ) {
13 | if (details.primaryDelta! > 3.0) {
14 | Navigator.of(context).pop();
15 | }
16 | }
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Scaffold(
21 | body: ListView(
22 | padding: EdgeInsets.zero,
23 | children: [
24 | GestureDetector(
25 | onVerticalDragUpdate: (details) =>
26 | _onVerticalDrag(details, context),
27 | child: Hero(
28 | tag: location!.title!,
29 | child: Image.network(
30 | location!.imageUrl!,
31 | fit: BoxFit.cover,
32 | ),
33 | ),
34 | ),
35 | ...List.generate((20), (index) {
36 | return Padding(
37 | padding: const EdgeInsets.all(8.0),
38 | child: ListTile(
39 | leading: CircleAvatar(
40 | backgroundImage: NetworkImage(avatars.last),
41 | radius: 15,
42 | ),
43 | title: Text('The Dart Side'),
44 | subtitle: Text(
45 | 'Come to the Dart Side :) ..... $index\nline 22222 \nline 33'),
46 | ),
47 | );
48 | })
49 | ],
50 | ),
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/appbar_sliverappbar/main_appbar_sliverappbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/appbar_sliverappbar/sample1.dart';
3 | import 'package:flutter_samples/appbar_sliverappbar/sample2.dart';
4 |
5 | import '../main.dart';
6 | import 'sample3.dart';
7 |
8 | class MainAppBarSliverAppBar extends StatelessWidget {
9 | onButtonTap(Widget page, BuildContext context) {
10 | Navigator.push(
11 | context, MaterialPageRoute(builder: (BuildContext context) => page));
12 | }
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | appBar: AppBar(
18 | title: Text("AppBar & SliverAppBar"),
19 | ),
20 | body: Padding(
21 | padding: EdgeInsets.all(15.0),
22 | child: ListView(
23 | children: [
24 | MyMenuButton(
25 | title: "Sample 1 - AppBar",
26 | actionTap: () {
27 | onButtonTap(Sample1(), context);
28 | },
29 | ),
30 | MyMenuButton(
31 | title: "Sample 2 - SliverAppBar",
32 | actionTap: () {
33 | onButtonTap(Sample2(), context);
34 | },
35 | ),
36 | MyMenuButton(
37 | title: "Sample 3 - SliverAppBar with Strech",
38 | actionTap: () {
39 | onButtonTap(Sample3(), context);
40 | },
41 | ),
42 | ],
43 | ),
44 | ),
45 | );
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/appbar_sliverappbar/sample1.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Sample1 extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return SafeArea(
7 | child: Scaffold(
8 | drawer: Drawer(),
9 | appBar: MyCustomAppBar(
10 | height: 150,
11 | defaultAppBar: true,
12 | ),
13 | body: Center(
14 | child: FlutterLogo(
15 | size: MediaQuery.of(context).size.width / 2,
16 | ),
17 | ),
18 | ),
19 | );
20 | }
21 | }
22 |
23 | class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget {
24 | final double height;
25 | final bool defaultAppBar;
26 |
27 | const MyCustomAppBar({
28 | Key? key,
29 | required this.height,
30 | this.defaultAppBar = true,
31 | }) : super(key: key);
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | return Column(
36 | children: [
37 | Container(
38 | color: Colors.grey[300],
39 | child: Padding(
40 | padding: EdgeInsets.all(30),
41 | child: defaultAppBar
42 | ? AppBar(
43 | title: Container(
44 | color: Colors.white,
45 | child: TextField(
46 | decoration: InputDecoration(
47 | hintText: "Search",
48 | contentPadding: EdgeInsets.all(10),
49 | ),
50 | ),
51 | ),
52 | actions: [
53 | IconButton(
54 | icon: Icon(Icons.verified_user),
55 | onPressed: () => null,
56 | ),
57 | ],
58 | )
59 | : _customAppBar(context),
60 | ),
61 | ),
62 | ],
63 | );
64 | }
65 |
66 | Widget _customAppBar(BuildContext context) {
67 | return Container(
68 | color: Colors.red,
69 | padding: EdgeInsets.all(5),
70 | child: Row(children: [
71 | IconButton(
72 | icon: Icon(Icons.menu),
73 | onPressed: () {
74 | Scaffold.of(context).openDrawer();
75 | },
76 | ),
77 | Expanded(
78 | child: Container(
79 | color: Colors.white,
80 | child: TextField(
81 | decoration: InputDecoration(
82 | hintText: "Search",
83 | contentPadding: EdgeInsets.all(10),
84 | ),
85 | ),
86 | ),
87 | ),
88 | IconButton(
89 | icon: Icon(Icons.verified_user),
90 | onPressed: () => null,
91 | ),
92 | ]),
93 | );
94 | }
95 |
96 | @override
97 | Size get preferredSize => Size.fromHeight(height);
98 | }
99 |
--------------------------------------------------------------------------------
/lib/appbar_sliverappbar/sample2.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class Sample2 extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return SafeArea(
7 | child: Scaffold(
8 | drawer: Drawer(),
9 | body: CustomScrollView(
10 | slivers: [
11 | SliverPersistentHeader(
12 | delegate: MySliverAppBar(expandedHeight: 200),
13 | pinned: true,
14 | ),
15 | SliverList(
16 | delegate: SliverChildBuilderDelegate(
17 | (_, index) => ListTile(
18 | title: Text("Index: $index"),
19 | ),
20 | ),
21 | )
22 | ],
23 | ),
24 | ),
25 | );
26 | }
27 | }
28 |
29 | class MySliverAppBar extends SliverPersistentHeaderDelegate {
30 | final double expandedHeight;
31 |
32 | MySliverAppBar({required this.expandedHeight});
33 |
34 | @override
35 | Widget build(
36 | BuildContext context, double shrinkOffset, bool overlapsContent) {
37 | return Stack(
38 | clipBehavior: Clip.none,
39 | fit: StackFit.expand,
40 | children: [
41 | Image.network(
42 | "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
43 | fit: BoxFit.cover,
44 | ),
45 | Center(
46 | child: Opacity(
47 | opacity: shrinkOffset / expandedHeight,
48 | child: Text(
49 | "MySliverAppBar",
50 | style: TextStyle(
51 | color: Colors.white,
52 | fontWeight: FontWeight.w700,
53 | fontSize: 23,
54 | ),
55 | ),
56 | ),
57 | ),
58 | Positioned(
59 | top: expandedHeight / 2 - shrinkOffset,
60 | left: MediaQuery.of(context).size.width / 4,
61 | child: Opacity(
62 | opacity: (1 - shrinkOffset / expandedHeight),
63 | child: Card(
64 | elevation: 10,
65 | child: SizedBox(
66 | height: expandedHeight,
67 | width: MediaQuery.of(context).size.width / 2,
68 | child: FlutterLogo(),
69 | ),
70 | ),
71 | ),
72 | ),
73 | Align(
74 | alignment: Alignment.topLeft,
75 | child: IconButton(
76 | icon: Icon(
77 | Icons.menu,
78 | color: Colors.white,
79 | ),
80 | onPressed: () {
81 | Scaffold.of(context).openDrawer();
82 | },
83 | ),
84 | ),
85 | ],
86 | );
87 | }
88 |
89 | @override
90 | double get maxExtent => expandedHeight;
91 |
92 | @override
93 | double get minExtent => kToolbarHeight;
94 |
95 | @override
96 | bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;
97 | }
98 |
--------------------------------------------------------------------------------
/lib/collapsing_toolbar/main_collapsing_toolbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MainCollapsingToolbar extends StatefulWidget {
4 | @override
5 | _MainCollapsingToolbarState createState() => _MainCollapsingToolbarState();
6 | }
7 |
8 | class _MainCollapsingToolbarState extends State {
9 | @override
10 | Widget build(BuildContext context) {
11 | return Scaffold(
12 | body: DefaultTabController(
13 | length: 2,
14 | child: NestedScrollView(
15 | headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
16 | return [
17 | SliverAppBar(
18 | expandedHeight: 200.0,
19 | floating: false,
20 | pinned: true,
21 | flexibleSpace: FlexibleSpaceBar(
22 | centerTitle: true,
23 | title: Text("Collapsing Toolbar",
24 | style: TextStyle(
25 | color: Colors.white,
26 | fontSize: 16.0,
27 | )),
28 | background: Image.network(
29 | "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&h=350",
30 | fit: BoxFit.cover,
31 | )),
32 | ),
33 | SliverPersistentHeader(
34 | delegate: _SliverAppBarDelegate(
35 | TabBar(
36 | labelColor: Colors.black87,
37 | unselectedLabelColor: Colors.grey,
38 | tabs: [
39 | Tab(icon: Icon(Icons.info), text: "Tab 1"),
40 | Tab(icon: Icon(Icons.lightbulb_outline), text: "Tab 2"),
41 | ],
42 | ),
43 | ),
44 | pinned: true,
45 | ),
46 | ];
47 | },
48 | body: Center(
49 | child: Text("Sample text"),
50 | ),
51 | ),
52 | ),
53 | );
54 | }
55 | }
56 |
57 | class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
58 | _SliverAppBarDelegate(this._tabBar);
59 |
60 | final TabBar _tabBar;
61 |
62 | @override
63 | double get minExtent => _tabBar.preferredSize.height;
64 | @override
65 | double get maxExtent => _tabBar.preferredSize.height;
66 |
67 | @override
68 | Widget build(
69 | BuildContext context, double shrinkOffset, bool overlapsContent) {
70 | return Container(
71 | child: _tabBar,
72 | );
73 | }
74 |
75 | @override
76 | bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
77 | return false;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/communication_widgets/child1_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/communication_widgets/parent_page.dart';
3 |
4 | class Child1Page extends StatefulWidget {
5 | final String? title;
6 | final ValueChanged? child2Action3;
7 | final ValueChanged? child2Action2;
8 |
9 | const Child1Page({
10 | Key? key,
11 | this.title,
12 | this.child2Action2,
13 | this.child2Action3,
14 | }) : super(key: key);
15 |
16 | @override
17 | Child1PageState createState() => Child1PageState();
18 | }
19 |
20 | class Child1PageState extends State {
21 | String value = "Page 1";
22 |
23 | @override
24 | Widget build(BuildContext context) {
25 | return Padding(
26 | padding: const EdgeInsets.all(15.0),
27 | child: Column(
28 | children: [
29 | Text(
30 | widget.title ?? value,
31 | style: Theme.of(context).primaryTextTheme.headline5,
32 | ),
33 | ElevatedButton(
34 | //Update Parent from Child 1
35 | child: Text("Action 2"),
36 | onPressed: () {
37 | widget.child2Action2!("Update from Child 1");
38 | },
39 | ),
40 | ElevatedButton(
41 | //Update Child 2 from Child 1
42 | child: Text("Action 3"),
43 | onPressed: () {
44 | widget.child2Action3!("Update from Child 1");
45 | },
46 | ),
47 | ElevatedButton(
48 | //Change Tab from Child 1 to Child 2
49 | child: Text("Action 4"),
50 | onPressed: () {
51 | final controller = ParentProvider.of(context)!.tabController!;
52 | controller.index = 1;
53 | },
54 | )
55 | ],
56 | ),
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/communication_widgets/child2_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/communication_widgets/parent_page.dart';
3 |
4 | class Child2Page extends StatefulWidget {
5 | final String? title;
6 |
7 | const Child2Page({
8 | Key? key,
9 | this.title,
10 | }) : super(key: key);
11 |
12 | @override
13 | Child2PageState createState() => Child2PageState();
14 | }
15 |
16 | class Child2PageState extends State {
17 | String value = "Page 2";
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | final title = ParentProvider.of(context)!.title;
22 | return Padding(
23 | padding: const EdgeInsets.all(15.0),
24 | child: Column(
25 | children: [
26 | Text(
27 | title ?? value,
28 | style: Theme.of(context).primaryTextTheme.headline5,
29 | ),
30 | ],
31 | ),
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/communication_widgets/main_communication_widgets.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/communication_widgets/parent_page.dart';
3 |
4 | class MainCommunicationWidgets extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Theme(
8 | data: ThemeData.dark(),
9 | child: Scaffold(
10 | appBar: AppBar(
11 | title: Text("Communication Widgets"),
12 | ),
13 | body: ParentPage(),
14 | ),
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/communication_widgets/parent_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/communication_widgets/child1_page.dart';
3 | import 'package:flutter_samples/communication_widgets/child2_page.dart';
4 |
5 | class ParentPage extends StatefulWidget {
6 | @override
7 | ParentPageState createState() => ParentPageState();
8 | }
9 |
10 | class ParentProvider extends InheritedWidget {
11 | final TabController? tabController;
12 | final Widget child;
13 | final String? title;
14 |
15 | ParentProvider({
16 | this.tabController,
17 | required this.child,
18 | this.title,
19 | }) : super(child: child);
20 |
21 | @override
22 | bool updateShouldNotify(ParentProvider oldWidget) {
23 | return true;
24 | }
25 |
26 | static ParentProvider? of(BuildContext context) =>
27 | context.dependOnInheritedWidgetOfExactType();
28 | }
29 |
30 | class ParentPageState extends State
31 | with SingleTickerProviderStateMixin {
32 | TabController? _controller;
33 | String myTitle = "My Parent Title";
34 | String? updateChild2Title;
35 | String? updateChild1Title;
36 |
37 | @override
38 | void initState() {
39 | _controller = TabController(
40 | length: 2,
41 | vsync: this,
42 | );
43 | super.initState();
44 | }
45 |
46 | @override
47 | void dispose() {
48 | _controller!.dispose();
49 | super.dispose();
50 | }
51 |
52 | updateChild2(String text) {
53 | setState(() {
54 | updateChild2Title = text;
55 | });
56 | }
57 |
58 | updateParent(String text) {
59 | setState(() {
60 | myTitle = text;
61 | });
62 | }
63 |
64 | @override
65 | Widget build(BuildContext context) {
66 | return ParentProvider(
67 | tabController: _controller,
68 | title: updateChild2Title,
69 | child: Column(
70 | children: [
71 | ListTile(
72 | title: Text(
73 | myTitle,
74 | textAlign: TextAlign.center,
75 | ),
76 | ),
77 | ElevatedButton(
78 | //Update Child 1 from Parent
79 | child: Text("Action 1"),
80 | onPressed: () {
81 | setState(() {
82 | updateChild1Title = "Update from Parent";
83 | });
84 | },
85 | ),
86 | TabBar(
87 | controller: _controller,
88 | tabs: [
89 | Tab(
90 | text: "First",
91 | icon: Icon(Icons.check_circle),
92 | ),
93 | Tab(
94 | text: "Second",
95 | icon: Icon(Icons.crop_square),
96 | )
97 | ],
98 | ),
99 | Expanded(
100 | child: TabBarView(
101 | controller: _controller,
102 | children: [
103 | Child1Page(
104 | title: updateChild1Title,
105 | child2Action2: updateParent,
106 | child2Action3: updateChild2,
107 | ),
108 | Child2Page(),
109 | ],
110 | ),
111 | )
112 | ],
113 | ),
114 | );
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/lib/fetch_data/main_fetch_data.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_samples/fetch_data/photo.dart';
5 | import 'package:http/http.dart' as http;
6 |
7 | class MainFetchData extends StatefulWidget {
8 | @override
9 | _MainFetchDataState createState() => _MainFetchDataState();
10 | }
11 |
12 | class _MainFetchDataState extends State {
13 | List list = [];
14 | var isLoading = false;
15 |
16 | _fetchData() async {
17 | setState(() {
18 | isLoading = true;
19 | });
20 | final response = await http
21 | .get(Uri.parse("https://jsonplaceholder.typicode.com/photos"));
22 | if (response.statusCode == 200) {
23 | list = (json.decode(response.body) as List)
24 | .map((data) => new Photo.fromJson(data))
25 | .toList();
26 | setState(() {
27 | isLoading = false;
28 | });
29 | } else {
30 | throw Exception('Failed to load photos');
31 | }
32 | }
33 |
34 | @override
35 | Widget build(BuildContext context) {
36 | return Scaffold(
37 | appBar: AppBar(
38 | title: Text("Fetch Data JSON"),
39 | ),
40 | bottomNavigationBar: Padding(
41 | padding: const EdgeInsets.all(8.0),
42 | child: ElevatedButton(
43 | child: Text("Fetch Data"),
44 | onPressed: _fetchData,
45 | ),
46 | ),
47 | body: isLoading
48 | ? Center(
49 | child: CircularProgressIndicator(),
50 | )
51 | : ListView.builder(
52 | itemCount: list.length,
53 | itemBuilder: (BuildContext context, int index) {
54 | return ListTile(
55 | contentPadding: EdgeInsets.all(10.0),
56 | title: Text(list[index].title!),
57 | trailing: Image.network(
58 | list[index].thumbnailUrl!,
59 | fit: BoxFit.cover,
60 | height: 40.0,
61 | width: 40.0,
62 | ),
63 | );
64 | }));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/fetch_data/photo.dart:
--------------------------------------------------------------------------------
1 | class Photo {
2 | final String? title;
3 | final String? thumbnailUrl;
4 |
5 | Photo._({this.title, this.thumbnailUrl});
6 |
7 | factory Photo.fromJson(Map json) {
8 | return Photo._(
9 | title: json['title'],
10 | thumbnailUrl: json['thumbnailUrl'],
11 | );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/hero_animations/hero_dialog_route.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class HeroDialogRoute extends PageRoute {
4 | HeroDialogRoute({this.builder}) : super();
5 |
6 | final WidgetBuilder? builder;
7 |
8 | @override
9 | bool get opaque => false;
10 |
11 | @override
12 | bool get barrierDismissible => true;
13 |
14 | @override
15 | Duration get transitionDuration => const Duration(milliseconds: 500);
16 |
17 | @override
18 | bool get maintainState => true;
19 |
20 | @override
21 | Color get barrierColor => Colors.black54;
22 |
23 | @override
24 | Widget buildTransitions(BuildContext context, Animation animation,
25 | Animation secondaryAnimation, Widget child) {
26 | return FadeTransition(
27 | opacity: CurvedAnimation(parent: animation, curve: Curves.easeOut),
28 | child: child);
29 | }
30 |
31 | @override
32 | Widget buildPage(BuildContext context, Animation animation,
33 | Animation secondaryAnimation) {
34 | return builder!(context);
35 | }
36 |
37 | @override
38 | String? get barrierLabel => null;
39 | }
40 |
--------------------------------------------------------------------------------
/lib/hero_animations/main_hero_animations.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/hero_animations/hero_dialog_route.dart';
3 | import 'package:flutter_samples/hero_animations/page1.dart';
4 | import 'package:flutter_samples/hero_animations/page2.dart';
5 |
6 | class MainHeroAnimationsPage extends StatefulWidget {
7 | @override
8 | _MainHeroAnimationsPageState createState() => _MainHeroAnimationsPageState();
9 | }
10 |
11 | class _MainHeroAnimationsPageState extends State {
12 | _onButtonTap(Widget page) {
13 | Navigator.push(
14 | context,
15 | MaterialPageRoute(
16 | fullscreenDialog: true, builder: (BuildContext context) => page));
17 | }
18 |
19 | _onButtonTapPopup(Widget page) {
20 | Navigator.push(
21 | context, HeroDialogRoute(builder: (BuildContext context) => page));
22 | }
23 |
24 | _onButtonTapCustom(Widget page) {
25 | Navigator.of(context).push(
26 | PageRouteBuilder(
27 | pageBuilder: (BuildContext context, Animation animation,
28 | Animation secondaryAnimation) {
29 | return AnimatedBuilder(
30 | animation: animation,
31 | builder: (BuildContext context, Widget? child) {
32 | return Opacity(
33 | opacity: animation.value,
34 | child: page,
35 | );
36 | });
37 | },
38 | transitionDuration: Duration(milliseconds: 600)),
39 | );
40 | }
41 |
42 | @override
43 | Widget build(BuildContext context) {
44 | return Scaffold(
45 | appBar: AppBar(
46 | title: Text("Hero Animations"),
47 | ),
48 | body: Container(
49 | child: Container(
50 | width: MediaQuery.of(context).size.width,
51 | child: Column(
52 | mainAxisAlignment: MainAxisAlignment.start,
53 | crossAxisAlignment: CrossAxisAlignment.center,
54 | children: [
55 | _buildCustomButton("Simple Hero", Page1()),
56 | _buildCustomButton("Two Heroes", Page2()),
57 | _buildCustomButton("Hero on Dialog", _buildPopUp(context),
58 | isPopup: true),
59 | _buildCustomButton("Custom Hero Animation", Page1(),
60 | isCustom: true),
61 | Hero(
62 | tag: "hero1",
63 | child: ClipOval(
64 | child: CustomLogo(
65 | size: 60.0,
66 | ),
67 | ),
68 | ),
69 | Hero(
70 | tag: "hero2",
71 | child: Material(
72 | color: Colors.transparent,
73 | child: Text(
74 | "Sample Hero",
75 | style: TextStyle(fontSize: 14.0, color: Colors.black),
76 | ),
77 | ))
78 | ],
79 | ),
80 | ),
81 | ),
82 | );
83 | }
84 |
85 | _buildCustomButton(String text, Widget page,
86 | {bool isPopup = false, bool isCustom = false}) {
87 | return Padding(
88 | padding: const EdgeInsets.all(8.0),
89 | child: MaterialButton(
90 | height: 40.0,
91 | padding: EdgeInsets.all(10.0),
92 | color: Colors.lightBlue,
93 | onPressed: () {
94 | if (isPopup) {
95 | _onButtonTapPopup(page);
96 | } else if (isCustom) {
97 | _onButtonTapCustom(page);
98 | } else {
99 | _onButtonTap(page);
100 | }
101 | },
102 | child: Text(
103 | text,
104 | textAlign: TextAlign.center,
105 | style: TextStyle(fontSize: 13.0),
106 | ),
107 | ),
108 | );
109 | }
110 |
111 | _buildPopUp(BuildContext context) {
112 | return Center(
113 | child: AlertDialog(
114 | title: Hero(
115 | tag: "hero2", child: Material(child: Text('You are my hero.'))),
116 | content: Container(
117 | child: Hero(
118 | tag: 'hero1',
119 | child: CustomLogo(
120 | size: 300.0,
121 | )),
122 | ),
123 | actions: [
124 | OutlinedButton(
125 | onPressed: () => Navigator.of(context).pop(),
126 | child: Icon(Icons.close),
127 | ),
128 | ],
129 | ),
130 | );
131 | }
132 | }
133 |
134 | class CustomLogo extends StatelessWidget {
135 | final double size;
136 |
137 | CustomLogo({this.size = 200.0});
138 |
139 | @override
140 | Widget build(BuildContext context) {
141 | return Container(
142 | color: Colors.lightBlueAccent,
143 | width: size,
144 | height: size,
145 | child: Center(
146 | child: Image.asset(
147 | "images/mario_logo.png",
148 | width: size,
149 | height: size,
150 | ),
151 | ),
152 | );
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/lib/hero_animations/page1.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/hero_animations/main_hero_animations.dart';
3 |
4 | class Page1 extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | body: Padding(
9 | padding: EdgeInsets.all(30.0),
10 | child: Stack(
11 | children: [
12 | Align(
13 | alignment: Alignment.center,
14 | child: Hero(
15 | tag: "hero1",
16 | child: Container(
17 | height: 250.0,
18 | width: 250.0,
19 | child: CustomLogo(),
20 | ),
21 | ),
22 | ),
23 | OutlinedButton(
24 | onPressed: () => Navigator.of(context).pop(),
25 | child: Icon(Icons.close),
26 | )
27 | ],
28 | ),
29 | ),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/hero_animations/page2.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/hero_animations/main_hero_animations.dart';
3 |
4 | class Page2 extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Scaffold(
8 | body: Padding(
9 | padding: EdgeInsets.all(30.0),
10 | child: Stack(
11 | children: [
12 | Align(
13 | alignment: Alignment.topCenter,
14 | child: Hero(
15 | tag: "hero1",
16 | child: Container(
17 | padding: EdgeInsets.only(top: 50.0),
18 | height: 250.0,
19 | width: 250.0,
20 | child: CustomLogo(),
21 | ),
22 | ),
23 | ),
24 | Align(
25 | alignment: Alignment.centerRight,
26 | child: Hero(
27 | tag: "hero2",
28 | child: Material(
29 | color: Colors.transparent,
30 | child: Text(
31 | "Hero Text",
32 | style: TextStyle(fontSize: 40.0),
33 | )),
34 | ),
35 | ),
36 | OutlinedButton(
37 | onPressed: () => Navigator.of(context).pop(),
38 | child: Icon(Icons.close),
39 | )
40 | ],
41 | ),
42 | ),
43 | );
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_samples/animations/main_animations.dart';
4 | import 'package:flutter_samples/app_clone/main_apps_clone.dart';
5 | import 'package:flutter_samples/appbar_sliverappbar/main_appbar_sliverappbar.dart';
6 | import 'package:flutter_samples/collapsing_toolbar/main_collapsing_toolbar.dart';
7 | import 'package:flutter_samples/communication_widgets/main_communication_widgets.dart';
8 | import 'package:flutter_samples/fetch_data/main_fetch_data.dart';
9 | import 'package:flutter_samples/hero_animations/main_hero_animations.dart';
10 | import 'package:flutter_samples/menu_navigations/main_menu_navigations.dart';
11 | import 'package:flutter_samples/persistent_tabbar/main_persistent_tabbar.dart';
12 | import 'package:flutter_samples/scroll_controller/main_scroll_controller.dart';
13 | import 'package:flutter_samples/size_and_position/main_size_and_position.dart';
14 | import 'package:flutter_samples/split_image/main_split_image.dart';
15 |
16 | void main() => runApp(MaterialApp(
17 | debugShowCheckedModeBanner: false,
18 | theme: ThemeData(
19 | primarySwatch: Colors.blue,
20 | ),
21 | home: MyApp(),
22 | ));
23 |
24 | class MyApp extends StatefulWidget {
25 | @override
26 | MyAppState createState() {
27 | return MyAppState();
28 | }
29 | }
30 |
31 | class MyAppState extends State {
32 | onButtonTap(Widget page) {
33 | Navigator.push(
34 | context, MaterialPageRoute(builder: (BuildContext context) => page));
35 | }
36 |
37 | @override
38 | Widget build(BuildContext context) {
39 | SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]);
40 | return Scaffold(
41 | appBar: AppBar(
42 | title: Text("Flutter Samples"),
43 | ),
44 | body: Padding(
45 | padding: EdgeInsets.all(15.0),
46 | child: ListView(
47 | children: [
48 | MyMenuButton(
49 | title: "Fetch Data JSON",
50 | actionTap: () {
51 | onButtonTap(
52 | MainFetchData(),
53 | );
54 | },
55 | ),
56 | MyMenuButton(
57 | title: "Persistent Tab Bar",
58 | actionTap: () {
59 | onButtonTap(
60 | MainPersistentTabBar(),
61 | );
62 | }),
63 | MyMenuButton(
64 | title: "Collapsing Toolbar",
65 | actionTap: () {
66 | onButtonTap(
67 | MainCollapsingToolbar(),
68 | );
69 | },
70 | ),
71 | MyMenuButton(
72 | title: "Hero Animations",
73 | actionTap: () {
74 | onButtonTap(
75 | MainHeroAnimationsPage(),
76 | );
77 | },
78 | ),
79 | MyMenuButton(
80 | title: "Size and Positions",
81 | actionTap: () {
82 | onButtonTap(
83 | MainSizeAndPosition(),
84 | );
85 | },
86 | ),
87 | MyMenuButton(
88 | title: "ScrollController and ScrollNotification",
89 | actionTap: () {
90 | onButtonTap(
91 | MainScrollController(),
92 | );
93 | },
94 | ),
95 | MyMenuButton(
96 | title: "Apps Clone",
97 | actionTap: () {
98 | onButtonTap(
99 | MainAppsClone(),
100 | );
101 | },
102 | ),
103 | MyMenuButton(
104 | title: "Animations",
105 | actionTap: () {
106 | onButtonTap(
107 | MainAnimations(),
108 | );
109 | },
110 | ),
111 | MyMenuButton(
112 | title: "Communication Widgets",
113 | actionTap: () {
114 | onButtonTap(
115 | MainCommunicationWidgets(),
116 | );
117 | },
118 | ),
119 | MyMenuButton(
120 | title: "Split Image",
121 | actionTap: () {
122 | onButtonTap(MainSplitImage());
123 | },
124 | ),
125 | MyMenuButton(
126 | title: "Custom AppBar & SliverAppBar",
127 | actionTap: () {
128 | onButtonTap(MainAppBarSliverAppBar());
129 | },
130 | ),
131 | MyMenuButton(
132 | title: "Menu Navigations",
133 | actionTap: () {
134 | onButtonTap(MainMenuNavigations());
135 | },
136 | ),
137 | ],
138 | ),
139 | ),
140 | );
141 | }
142 | }
143 |
144 | class MyMenuButton extends StatelessWidget {
145 | final String? title;
146 | final VoidCallback? actionTap;
147 |
148 | MyMenuButton({this.title, this.actionTap});
149 |
150 | @override
151 | Widget build(BuildContext context) {
152 | return Padding(
153 | padding: const EdgeInsets.all(15.0),
154 | child: MaterialButton(
155 | height: 50.0,
156 | color: Theme.of(context).primaryColor,
157 | textColor: Colors.white,
158 | child: new Text(title!),
159 | onPressed: actionTap,
160 | ),
161 | );
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/lib/menu_navigations/content_navigation.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ContentNavigation extends StatelessWidget {
4 | final Color? color;
5 |
6 | const ContentNavigation({Key? key, this.color}) : super(key: key);
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return GridView.count(
11 | crossAxisCount: 2,
12 | childAspectRatio: 1 / 1.5,
13 | mainAxisSpacing: 10,
14 | crossAxisSpacing: 15,
15 | padding: const EdgeInsets.all(15),
16 | children: [
17 | ContentItem(
18 | color: color,
19 | ),
20 | ContentItem(
21 | color: color,
22 | ),
23 | ContentItem(
24 | color: color,
25 | ),
26 | ContentItem(
27 | color: color,
28 | ),
29 | ],
30 | );
31 | }
32 | }
33 |
34 | class ContentItem extends StatelessWidget {
35 | final Color? color;
36 |
37 | const ContentItem({Key? key, this.color}) : super(key: key);
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return Container(
42 | color: color!.withOpacity(0.5),
43 | alignment: Alignment.bottomCenter,
44 | child: Padding(
45 | padding: const EdgeInsets.all(8.0),
46 | child: Column(
47 | mainAxisSize: MainAxisSize.min,
48 | crossAxisAlignment: CrossAxisAlignment.stretch,
49 | children: [
50 | Container(
51 | height: 7,
52 | color: color!.withOpacity(0.6),
53 | ),
54 | const SizedBox(
55 | height: 5,
56 | ),
57 | Container(
58 | height: 7,
59 | margin: const EdgeInsets.only(right: 10),
60 | color: color!.withOpacity(0.6),
61 | ),
62 | const SizedBox(
63 | height: 15,
64 | ),
65 | ],
66 | ),
67 | ),
68 | );
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/lib/menu_navigations/header_navigation/main_header_navigation.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/menu_navigations/content_navigation.dart';
3 | import 'package:flutter_samples/menu_navigations/header_navigation/header_navigation.dart';
4 |
5 | class MainHeaderNavigation extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) {
8 | return SafeArea(
9 | child: Scaffold(
10 | body: HeaderNavigation(
11 | items: [
12 | HeaderNavigationItem(
13 | colorBackground: Colors.purple,
14 | title: "SERVICES",
15 | colorForeground: Colors.white,
16 | icon: Icon(
17 | Icons.room_service,
18 | size: 45,
19 | ),
20 | child: ContentNavigation(
21 | color: Colors.purple,
22 | ),
23 | ),
24 | HeaderNavigationItem(
25 | colorBackground: Colors.red,
26 | title: "AUTO",
27 | colorForeground: Colors.white,
28 | icon: Icon(
29 | Icons.directions_car,
30 | size: 45,
31 | ),
32 | child: ContentNavigation(
33 | color: Colors.red,
34 | ),
35 | ),
36 | HeaderNavigationItem(
37 | colorBackground: Colors.green,
38 | title: "JOB",
39 | colorForeground: Colors.white,
40 | icon: Icon(
41 | Icons.person,
42 | size: 45,
43 | ),
44 | child: ContentNavigation(
45 | color: Colors.green,
46 | ),
47 | ),
48 | HeaderNavigationItem(
49 | colorBackground: Colors.blue,
50 | title: "REALTY",
51 | colorForeground: Colors.white,
52 | icon: Icon(
53 | Icons.home,
54 | size: 45,
55 | ),
56 | child: ContentNavigation(
57 | color: Colors.blue,
58 | ),
59 | ),
60 | ],
61 | ),
62 | ),
63 | );
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/menu_navigations/main_menu_navigations.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/main.dart';
3 | import 'package:flutter_samples/menu_navigations/header_navigation/main_header_navigation.dart';
4 |
5 | class MainMenuNavigations extends StatelessWidget {
6 | onButtonTap(Widget page, BuildContext context) {
7 | Navigator.push(
8 | context, MaterialPageRoute(builder: (BuildContext context) => page));
9 | }
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return Scaffold(
14 | appBar: AppBar(
15 | title: Text("Flutter Menu Navigations"),
16 | ),
17 | body: Padding(
18 | padding: EdgeInsets.all(15.0),
19 | child: ListView(
20 | children: [
21 | MyMenuButton(
22 | title: "Header Navigation",
23 | actionTap: () {
24 | onButtonTap(MainHeaderNavigation(), context);
25 | },
26 | ),
27 | ],
28 | ),
29 | ),
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/persistent_tabbar/main_persistent_tabbar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/persistent_tabbar/page1.dart';
3 | import 'package:flutter_samples/persistent_tabbar/page2.dart';
4 |
5 | class MainPersistentTabBar extends StatelessWidget {
6 | @override
7 | Widget build(BuildContext context) {
8 | return DefaultTabController(
9 | length: 4,
10 | child: Scaffold(
11 | appBar: AppBar(
12 | bottom: TabBar(
13 | isScrollable: true,
14 | tabs: [
15 | Tab(
16 | icon: Icon(Icons.directions_car),
17 | text: "Non persistent",
18 | ),
19 | Tab(icon: Icon(Icons.directions_transit), text: "Persistent"),
20 | Tab(icon: Icon(Icons.directions_railway), text: "Test 1"),
21 | Tab(icon: Icon(Icons.directions_subway), text: "Test 2"),
22 | ],
23 | ),
24 | title: Text('Persistent Tab Demo'),
25 | ),
26 | body: TabBarView(
27 | children: [
28 | Page1(),
29 | Page2(),
30 | Text('Page 3'),
31 | Text('Page 4'),
32 | ],
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/persistent_tabbar/page1.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'dart:convert';
4 | import 'package:http/http.dart' as http;
5 |
6 | class Page1 extends StatefulWidget {
7 | @override
8 | _Page1State createState() => _Page1State();
9 | }
10 |
11 | class _Page1State extends State {
12 | List? list = [];
13 |
14 | _loadList() async {
15 | final response = await http
16 | .get(Uri.parse("https://jsonplaceholder.typicode.com/posts/"));
17 | if (response.statusCode == 200) {
18 | await Future.delayed(const Duration(seconds: 1));
19 | if (mounted) {
20 | setState(() {
21 | list = json.decode(response.body) as List?;
22 | });
23 | }
24 | } else {
25 | throw Exception('Failed to load posts');
26 | }
27 | }
28 |
29 | @override
30 | void initState() {
31 | _loadList();
32 | super.initState();
33 | }
34 |
35 | @override
36 | Widget build(BuildContext context) {
37 | return Column(
38 | children: [
39 | Expanded(
40 | child: ListView.builder(
41 | itemCount: list!.length,
42 | itemBuilder: (BuildContext context, int index) {
43 | final data = list![index];
44 | return ListTile(
45 | contentPadding: EdgeInsets.all(10.0),
46 | title: Text(data['title']),
47 | subtitle: Text(
48 | data['body'],
49 | maxLines: 2,
50 | overflow: TextOverflow.ellipsis,
51 | ),
52 | );
53 | },
54 | ),
55 | ),
56 | ],
57 | );
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/persistent_tabbar/page2.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'package:flutter/material.dart';
3 | import 'dart:convert';
4 | import 'package:http/http.dart' as http;
5 |
6 | class Page2 extends StatefulWidget {
7 | @override
8 | _Page2State createState() => _Page2State();
9 | }
10 |
11 | class _Page2State extends State
12 | with AutomaticKeepAliveClientMixin {
13 | List? list = [];
14 |
15 | _loadList() async {
16 | final response = await http
17 | .get(Uri.parse("https://jsonplaceholder.typicode.com/photos/"));
18 | if (response.statusCode == 200) {
19 | await Future.delayed(const Duration(seconds: 1));
20 | if (mounted) {
21 | setState(() {
22 | list = json.decode(response.body) as List?;
23 | });
24 | }
25 | } else {
26 | throw Exception('Failed to load posts');
27 | }
28 | }
29 |
30 | @override
31 | void initState() {
32 | _loadList();
33 | super.initState();
34 | }
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | super.build(context);
39 | return Column(
40 | children: [
41 | Expanded(
42 | child: ListView.builder(
43 | itemCount: list!.length,
44 | itemBuilder: (BuildContext context, int index) {
45 | final data = list![index];
46 | return ListTile(
47 | contentPadding: EdgeInsets.all(10.0),
48 | title: Text(data['title']),
49 | trailing: Image.network(
50 | data['thumbnailUrl'],
51 | height: 20.0,
52 | width: 20.0,
53 | ),
54 | );
55 | },
56 | ),
57 | ),
58 | ],
59 | );
60 | }
61 |
62 | @override
63 | bool get wantKeepAlive => true;
64 | }
65 |
--------------------------------------------------------------------------------
/lib/scroll_controller/main_scroll_controller.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_samples/main.dart';
3 | import 'package:flutter_samples/scroll_controller/scroll_limit_reached.dart';
4 | import 'package:flutter_samples/scroll_controller/scroll_movement.dart';
5 | import 'package:flutter_samples/scroll_controller/scroll_status.dart';
6 | import 'package:flutter_samples/scroll_controller/scroll_sync/scroll_sync.dart';
7 |
8 | class MainScrollController extends StatelessWidget {
9 | onButtonTap(Widget page, BuildContext context) {
10 | Navigator.push(
11 | context, MaterialPageRoute(builder: (BuildContext context) => page));
12 | }
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | appBar: AppBar(
18 | title: Text("ScrollController / ScrollNotifiation"),
19 | ),
20 | body: Padding(
21 | padding: EdgeInsets.all(15.0),
22 | child: ListView(
23 | children: [
24 | MyMenuButton(
25 | title: "Scroll Limit Reached",
26 | actionTap: () {
27 | onButtonTap(ScrollLimitReached(), context);
28 | },
29 | ),
30 | MyMenuButton(
31 | title: "Scroll Movement",
32 | actionTap: () {
33 | onButtonTap(ScrollMovement(), context);
34 | },
35 | ),
36 | MyMenuButton(
37 | title: "Scroll Status",
38 | actionTap: () {
39 | onButtonTap(ScrollStatus(), context);
40 | },
41 | ),
42 | MyMenuButton(
43 | title: "Scroll Sync",
44 | actionTap: () {
45 | onButtonTap(ScrollSync(), context);
46 | },
47 | ),
48 | ],
49 | ),
50 | ),
51 | );
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/scroll_controller/scroll_limit_reached.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollLimitReached extends StatefulWidget {
4 | @override
5 | _ScrollLimitReachedState createState() => _ScrollLimitReachedState();
6 | }
7 |
8 | class _ScrollLimitReachedState extends State {
9 | ScrollController? _controller;
10 | String message = "";
11 |
12 | _scrollListener() {
13 | if (_controller!.offset >= _controller!.position.maxScrollExtent &&
14 | !_controller!.position.outOfRange) {
15 | setState(() {
16 | message = "reach the bottom";
17 | });
18 | }
19 | if (_controller!.offset <= _controller!.position.minScrollExtent &&
20 | !_controller!.position.outOfRange) {
21 | setState(() {
22 | message = "reach the top";
23 | });
24 | }
25 | }
26 |
27 | @override
28 | void initState() {
29 | _controller = ScrollController();
30 | _controller!.addListener(_scrollListener);
31 | super.initState();
32 | }
33 |
34 | @override
35 | void dispose() {
36 | _controller!.removeListener(_scrollListener);
37 | _controller!.dispose();
38 | super.dispose();
39 | }
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | return Scaffold(
44 | appBar: AppBar(
45 | title: Text("Scroll Limit reached"),
46 | ),
47 | body: Column(
48 | children: [
49 | Container(
50 | height: 50.0,
51 | color: Colors.green,
52 | child: Center(
53 | child: Text(message),
54 | ),
55 | ),
56 | Expanded(
57 | child: ListView.builder(
58 | controller: _controller,
59 | itemCount: 30,
60 | itemBuilder: (context, index) {
61 | return ListTile(title: Text("Index : $index"));
62 | },
63 | ),
64 | ),
65 | ],
66 | ),
67 | );
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/scroll_controller/scroll_movement.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollMovement extends StatefulWidget {
4 | @override
5 | _ScrollMovementState createState() => _ScrollMovementState();
6 | }
7 |
8 | class _ScrollMovementState extends State {
9 | ScrollController? _controller;
10 | final itemSize = 100.0;
11 |
12 | _moveUp() {
13 | //_controller.jumpTo(_controller.offset - itemSize);
14 | _controller!.animateTo(_controller!.offset - itemSize,
15 | curve: Curves.linear, duration: Duration(milliseconds: 500));
16 | }
17 |
18 | _moveDown() {
19 | //_controller.jumpTo(_controller.offset + itemSize);
20 | _controller!.animateTo(_controller!.offset + itemSize,
21 | curve: Curves.linear, duration: Duration(milliseconds: 500));
22 | }
23 |
24 | @override
25 | void initState() {
26 | _controller = ScrollController();
27 | super.initState();
28 | }
29 |
30 | @override
31 | void dispose() {
32 | _controller!.dispose();
33 | super.dispose();
34 | }
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | return Scaffold(
39 | appBar: AppBar(
40 | title: Text("Scroll Movement"),
41 | ),
42 | body: Column(
43 | children: [
44 | Container(
45 | height: 50.0,
46 | color: Colors.green,
47 | child: Center(
48 | child: Row(
49 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
50 | children: [
51 | ElevatedButton(
52 | child: Text("up"),
53 | onPressed: _moveUp,
54 | ),
55 | ElevatedButton(
56 | child: Text("down"),
57 | onPressed: _moveDown,
58 | )
59 | ],
60 | ),
61 | ),
62 | ),
63 | Expanded(
64 | child: ListView.builder(
65 | controller: _controller,
66 | itemCount: 30,
67 | itemExtent: itemSize,
68 | itemBuilder: (context, index) {
69 | return ListTile(title: Text("Index : $index"));
70 | },
71 | ),
72 | ),
73 | ],
74 | ),
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/scroll_controller/scroll_status.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollStatus extends StatefulWidget {
4 | @override
5 | _ScrollStatusState createState() => _ScrollStatusState();
6 | }
7 |
8 | class _ScrollStatusState extends State {
9 | String message = "";
10 |
11 | _onStartScroll(ScrollMetrics metrics) {
12 | setState(() {
13 | message = "Scroll Start";
14 | });
15 | }
16 |
17 | _onUpdateScroll(ScrollMetrics metrics) {
18 | setState(() {
19 | message = "Scroll Update";
20 | });
21 | }
22 |
23 | _onEndScroll(ScrollMetrics metrics) {
24 | setState(() {
25 | message = "Scroll End";
26 | });
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | return Scaffold(
32 | appBar: AppBar(
33 | title: Text("Scroll Status"),
34 | ),
35 | body: Column(
36 | children: [
37 | Container(
38 | height: 50.0,
39 | color: Colors.green,
40 | child: Center(
41 | child: Text(message),
42 | ),
43 | ),
44 | Expanded(
45 | child: NotificationListener(
46 | onNotification: (scrollNotification) {
47 | if (scrollNotification is ScrollStartNotification) {
48 | _onStartScroll(scrollNotification.metrics);
49 | } else if (scrollNotification is ScrollUpdateNotification) {
50 | _onUpdateScroll(scrollNotification.metrics);
51 | } else if (scrollNotification is ScrollEndNotification) {
52 | _onEndScroll(scrollNotification.metrics);
53 | }
54 | return false;
55 | },
56 | child: ListView.builder(
57 | itemCount: 30,
58 | itemBuilder: (context, index) {
59 | return ListTile(title: Text("Index : $index"));
60 | },
61 | ),
62 | ),
63 | ),
64 | ],
65 | ),
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/scroll_controller/scroll_sync/scroll_sync.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class ScrollSync extends StatefulWidget {
4 | @override
5 | _ScrollSyncState createState() => _ScrollSyncState();
6 | }
7 |
8 | class _ScrollSyncState extends State {
9 | CustomScrollController _controller1 = CustomScrollController();
10 | CustomScrollController _controller2 = CustomScrollController();
11 |
12 | @override
13 | void initState() {
14 | _controller1.addListener(() => _controller2
15 | .jumpToWithoutGoingIdleAndKeepingBallistic(_controller1.offset));
16 | _controller2.addListener(() => _controller1
17 | .jumpToWithoutGoingIdleAndKeepingBallistic(_controller2.offset));
18 | super.initState();
19 | }
20 |
21 | @override
22 | void dispose() {
23 | _controller1.dispose();
24 | _controller2.dispose();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return Scaffold(
31 | appBar: AppBar(
32 | title: Text("Scroll Sync"),
33 | ),
34 | body: Column(
35 | children: [
36 | Flexible(
37 | flex: 1,
38 | child: ListView.builder(
39 | controller: _controller1,
40 | scrollDirection: Axis.horizontal,
41 | itemBuilder: (_, index) => Container(
42 | color: Colors.red,
43 | width: 150,
44 | margin: EdgeInsets.all(10.0),
45 | child: Center(
46 | child: Text(
47 | "$index",
48 | textAlign: TextAlign.center,
49 | style: Theme.of(context).textTheme.headline3,
50 | ),
51 | ),
52 | ),
53 | ),
54 | ),
55 | Flexible(
56 | flex: 3,
57 | child: ListView.builder(
58 | controller: _controller2,
59 | itemBuilder: (_, index) => Container(
60 | color: Colors.black,
61 | margin: EdgeInsets.all(10.0),
62 | child: Center(
63 | child: Text(
64 | "$index",
65 | style: Theme.of(context)
66 | .textTheme
67 | .headline3!
68 | .copyWith(color: Colors.white),
69 | ),
70 | ),
71 | ),
72 | ),
73 | ),
74 | ],
75 | ),
76 | );
77 | }
78 | }
79 |
80 | class CustomScrollController extends ScrollController {
81 | CustomScrollController({
82 | double initialScrollOffset = 0.0,
83 | keepScrollOffset = true,
84 | debugLabel,
85 | }) : super(
86 | initialScrollOffset: initialScrollOffset,
87 | keepScrollOffset: keepScrollOffset,
88 | debugLabel: debugLabel);
89 |
90 | @override
91 | _SilentScrollPosition createScrollPosition(
92 | ScrollPhysics physics,
93 | ScrollContext context,
94 | ScrollPosition? oldPosition,
95 | ) {
96 | return _SilentScrollPosition(
97 | physics: physics,
98 | context: context,
99 | oldPosition: oldPosition,
100 | initialPixels: initialScrollOffset,
101 | );
102 | }
103 |
104 | void jumpToWithoutGoingIdleAndKeepingBallistic(double value) {
105 | assert(positions.isNotEmpty, 'ScrollController not attached.');
106 | for (_SilentScrollPosition position
107 | in new List.from(positions)
108 | as Iterable<_SilentScrollPosition>)
109 | position.jumpToWithoutGoingIdleAndKeepingBallistic(value);
110 | }
111 | }
112 |
113 | class _SilentScrollPosition extends ScrollPositionWithSingleContext {
114 | _SilentScrollPosition({
115 | required ScrollPhysics physics,
116 | required ScrollContext context,
117 | ScrollPosition? oldPosition,
118 | double? initialPixels,
119 | }) : super(
120 | physics: physics,
121 | context: context,
122 | oldPosition: oldPosition,
123 | initialPixels: initialPixels,
124 | );
125 |
126 | void jumpToWithoutGoingIdleAndKeepingBallistic(double value) {
127 | if (pixels != value) {
128 | forcePixels(value);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/lib/size_and_position/main_size_and_position.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class MainSizeAndPosition extends StatefulWidget {
4 | @override
5 | _MainSizeAndPositionState createState() => _MainSizeAndPositionState();
6 | }
7 |
8 | class _MainSizeAndPositionState extends State {
9 | GlobalKey _keyRed = GlobalKey();
10 | GlobalKey _keyPurple = GlobalKey();
11 | GlobalKey _keyGreen = GlobalKey();
12 |
13 | _getSizes() {
14 | final RenderBox renderBoxRed =
15 | _keyRed.currentContext!.findRenderObject() as RenderBox;
16 | final sizeRed = renderBoxRed.size;
17 |
18 | final RenderBox renderBoxPurple =
19 | _keyPurple.currentContext!.findRenderObject() as RenderBox;
20 | final sizePurple = renderBoxPurple.size;
21 |
22 | final RenderBox renderBoxGreen =
23 | _keyGreen.currentContext!.findRenderObject() as RenderBox;
24 | final sizeGreen = renderBoxGreen.size;
25 |
26 | print("SIZE of Red: $sizeRed");
27 | print("SIZE of Purple: $sizePurple");
28 | print("SIZE of Green: $sizeGreen");
29 | }
30 |
31 | _getPositions() {
32 | final RenderBox renderBoxRed =
33 | _keyRed.currentContext!.findRenderObject() as RenderBox;
34 | final positionRed = renderBoxRed.localToGlobal(Offset.zero);
35 |
36 | final RenderBox renderBoxPurple =
37 | _keyPurple.currentContext!.findRenderObject() as RenderBox;
38 | final positionPurple = renderBoxPurple.localToGlobal(Offset.zero);
39 |
40 | final RenderBox renderBoxGreen =
41 | _keyGreen.currentContext!.findRenderObject() as RenderBox;
42 | final positionGreen = renderBoxGreen.localToGlobal(Offset.zero);
43 |
44 | print("POSITION of Red: $positionRed ");
45 | print("POSITION of Purple: $positionPurple ");
46 | print("POSITION of Green: $positionGreen ");
47 | }
48 |
49 | _afterLayout(_) {
50 | _getSizes();
51 | _getPositions();
52 | }
53 |
54 | @override
55 | void initState() {
56 | WidgetsBinding.instance!.addPostFrameCallback(_afterLayout);
57 | super.initState();
58 | }
59 |
60 | @override
61 | Widget build(BuildContext context) {
62 | return Scaffold(
63 | appBar: AppBar(),
64 | body: Column(
65 | children: [
66 | Flexible(
67 | flex: 2,
68 | child: Container(
69 | key: _keyRed,
70 | color: Colors.red,
71 | ),
72 | ),
73 | Flexible(
74 | flex: 1,
75 | child: Container(
76 | key: _keyPurple,
77 | color: Colors.purple,
78 | ),
79 | ),
80 | Flexible(
81 | flex: 3,
82 | child: Container(
83 | key: _keyGreen,
84 | color: Colors.green,
85 | ),
86 | ),
87 | Spacer(),
88 | Padding(
89 | padding: const EdgeInsets.only(bottom: 8.0),
90 | child: Row(
91 | mainAxisAlignment: MainAxisAlignment.spaceAround,
92 | crossAxisAlignment: CrossAxisAlignment.center,
93 | children: [
94 | MaterialButton(
95 | elevation: 5.0,
96 | padding: EdgeInsets.all(15.0),
97 | color: Colors.grey,
98 | child: Text("Get Sizes"),
99 | onPressed: _getSizes,
100 | ),
101 | MaterialButton(
102 | elevation: 5.0,
103 | color: Colors.grey,
104 | padding: EdgeInsets.all(15.0),
105 | child: Text("Get Positions"),
106 | onPressed: _getPositions,
107 | )
108 | ],
109 | ),
110 | )
111 | ],
112 | ),
113 | );
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/lib/split_image/main_split_image.dart:
--------------------------------------------------------------------------------
1 | import 'dart:typed_data';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter/material.dart';
4 | import 'dart:ui' as ui;
5 |
6 | class MainSplitImage extends StatefulWidget {
7 | @override
8 | _MainSplitImageState createState() => _MainSplitImageState();
9 | }
10 |
11 | class _MainSplitImageState extends State {
12 | ui.Image? _image;
13 | double _x = 0, _y = 0, _width = 0, _height = 0;
14 |
15 | _loadImage() async {
16 | final assetImage =
17 | AssetImage("images/characters/broly.png", bundle: rootBundle);
18 | final imageKey = await assetImage.obtainKey(ImageConfiguration());
19 | final DecoderCallback decodeResize = (Uint8List bytes,
20 | {bool? allowUpscaling, int? cacheWidth, int? cacheHeight}) {
21 | return ui.instantiateImageCodec(bytes,
22 | targetHeight: cacheHeight, targetWidth: cacheWidth);
23 | };
24 | var load = assetImage.load(imageKey, decodeResize);
25 |
26 | ImageStreamListener listener = ImageStreamListener((info, err) async {
27 | setState(() {
28 | _image = info.image;
29 | });
30 | });
31 | load.addListener(listener);
32 | }
33 |
34 | _reset() {
35 | setState(() {
36 | _x = 0;
37 | _y = 0;
38 | _width = 0;
39 | _height = 0;
40 | });
41 | }
42 |
43 | _crop() {
44 | setState(() {
45 | _x = 120;
46 | _y = 80;
47 | _width = 100;
48 | _height = 100;
49 | });
50 | }
51 |
52 | @override
53 | void initState() {
54 | _loadImage();
55 | super.initState();
56 | }
57 |
58 | @override
59 | Widget build(BuildContext context) {
60 | return Scaffold(
61 | appBar: AppBar(
62 | title: Text("Split Image"),
63 | actions: [
64 | IconButton(
65 | icon: Icon(Icons.refresh),
66 | onPressed: _reset,
67 | ),
68 | IconButton(
69 | icon: Icon(Icons.crop),
70 | onPressed: _crop,
71 | )
72 | ],
73 | ),
74 | body: Center(
75 | child: CustomPaint(
76 | child: Container(),
77 | painter: ImagePainter(
78 | image: _image,
79 | x: _x,
80 | y: _y,
81 | height: _height,
82 | width: _width,
83 | ),
84 | ),
85 | ),
86 | );
87 | }
88 | }
89 |
90 | class ImagePainter extends CustomPainter {
91 | final ui.Image? image;
92 | final double? width;
93 | final double? height;
94 | final double? x;
95 | final double? y;
96 |
97 | ImagePainter({
98 | this.image,
99 | this.width,
100 | this.height,
101 | this.x,
102 | this.y,
103 | });
104 |
105 | @override
106 | void paint(Canvas canvas, Size size) {
107 | if (image != null) {
108 | if (width != 0 && height != 0 && x != 0 && y != 0) {
109 | //crop
110 | canvas.clipRect(Rect.fromLTWH(x!, y!, width!, height!));
111 | }
112 | //resize Image
113 | final ui.Rect rect = ui.Offset.zero & size;
114 | final Size imageSize =
115 | Size(image!.width.toDouble(), image!.height.toDouble());
116 | FittedSizes sizes = applyBoxFit(BoxFit.fitWidth, imageSize, size);
117 | final Rect inputSubrect =
118 | Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
119 | final Rect outputSubrect =
120 | Alignment.center.inscribe(sizes.destination, rect);
121 |
122 | canvas.drawImageRect(image!, inputSubrect, outputSubrect, Paint());
123 | }
124 | }
125 |
126 | @override
127 | bool shouldRepaint(CustomPainter oldDelegate) {
128 | return true;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_samples
2 | description: A new Flutter project.
3 | version: 1.0.0
4 | environment:
5 | sdk: '>=2.12.0 <3.0.0'
6 | dependencies:
7 | flutter:
8 | sdk: flutter
9 |
10 | # The following adds the Cupertino Icons font to your application.
11 | # Use with the CupertinoIcons class for iOS style icons.
12 | cupertino_icons: ^1.0.3
13 | http: any
14 | circle_wheel_scroll:
15 | git:
16 | url: https://github.com/KolasikOmetov/circle_wheel_scroll
17 | ref: null_safety_and_endless_scrolling
18 | cached_network_image: ^3.1.0
19 |
20 | dev_dependencies:
21 | flutter_test:
22 | sdk: flutter
23 |
24 |
25 | # For information on the generic Dart part of this file, see the
26 | # following page: https://www.dartlang.org/tools/pub/pubspec
27 |
28 | # The following section is specific to Flutter.
29 | flutter:
30 |
31 | # The following line ensures that the Material Icons font is
32 | # included with your application, so that you can use the icons in
33 | # the material Icons class.
34 | uses-material-design: true
35 |
36 | # To add assets to your application, add an assets section, like this:
37 |
38 | # An image asset can refer to one or more resolution-specific "variants", see
39 | # https://flutter.io/assets-and-images/#resolution-aware.
40 |
41 | # For details regarding adding assets from package dependencies, see
42 | # https://flutter.io/assets-and-images/#from-packages
43 |
44 | assets:
45 | - images/
46 | - images/characters/
47 | - images/balls/
48 | - images/shoes/
49 | - images/credit_cards/
50 | - assets/
51 |
52 | # To add custom fonts to your application, add a fonts section here,
53 | # in this "flutter" section. Each entry in this list should have a
54 | # "family" key with the font family name, and a "fonts" key with a
55 | # list giving the asset and other descriptors for the font. For
56 | # example:
57 | # fonts:
58 | # - family: Schyler
59 | # fonts:
60 | # - asset: fonts/Schyler-Regular.ttf
61 | # - asset: fonts/Schyler-Italic.ttf
62 | # style: italic
63 | # - family: Trajan Pro
64 | # fonts:
65 | # - asset: fonts/TrajanPro.ttf
66 | # - asset: fonts/TrajanPro_Bold.ttf
67 | # weight: 700
68 | #
69 | # For details regarding fonts from package dependencies,
70 | # see https://flutter.io/custom-fonts/#from-packages
71 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter
3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to
4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties
5 | // are correct.
6 |
7 | import 'package:flutter/material.dart';
8 | import 'package:flutter_test/flutter_test.dart';
9 |
10 | import 'package:flutter_samples/main.dart';
11 |
12 | void main() {
13 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
14 | // Build our app and trigger a frame.
15 | await tester.pumpWidget(new MyApp());
16 |
17 | // Verify that our counter starts at 0.
18 | expect(find.text('0'), findsOneWidget);
19 | expect(find.text('1'), findsNothing);
20 |
21 | // Tap the '+' icon and trigger a frame.
22 | await tester.tap(find.byIcon(Icons.add));
23 | await tester.pump();
24 |
25 | // Verify that our counter has incremented.
26 | expect(find.text('0'), findsNothing);
27 | expect(find.text('1'), findsOneWidget);
28 | });
29 | }
30 |
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | flutter_samples
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------