├── .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 | --------------------------------------------------------------------------------