├── .gitignore
├── .metadata
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── brocodev
│ │ │ │ └── flutter_community_challenges
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── settings_aar.gradle
├── assets
├── bank_challenge
│ └── img
│ │ ├── bbva-background.jpg
│ │ ├── bbva-logo.png
│ │ ├── citi-background.jpg
│ │ ├── citi-logo.png
│ │ ├── hbo-max-logo.webp
│ │ ├── netflix-logo.jpg
│ │ ├── red-bg.jpg
│ │ ├── san-logo.png
│ │ ├── santander-background.jpg
│ │ ├── save-money.jpg
│ │ ├── user1.jpg
│ │ ├── user2.jpg
│ │ ├── user3.jpg
│ │ ├── user4.jpg
│ │ ├── user5.jpg
│ │ ├── user6.jpg
│ │ ├── user7.jpg
│ │ └── user8.jpg
├── boats_challenge
│ └── img
│ │ ├── boat1.png
│ │ ├── boat2.png
│ │ ├── boat3.png
│ │ ├── boat4.png
│ │ ├── gallery1.jpg
│ │ ├── gallery2.jpg
│ │ ├── gallery3.jpg
│ │ ├── gallery4.jpg
│ │ └── gallery5.jpg
└── coffee_challenge
│ ├── img
│ ├── 1.png
│ ├── 10.png
│ ├── 11.png
│ ├── 12.png
│ ├── 2.png
│ ├── 3.png
│ ├── 4.png
│ ├── 5.png
│ ├── 6.png
│ ├── 7.png
│ ├── 8.png
│ ├── 9.png
│ └── names.MD
│ └── svg
│ ├── b-coffee-cup.svg
│ ├── m-coffee-cup.svg
│ └── s-coffee-cup.svg
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── bank_challenge
│ ├── bank_challenge_app.dart
│ ├── model
│ │ └── bank_models.dart
│ ├── ui
│ │ ├── home_page.dart
│ │ └── widgets
│ │ │ ├── account_card.dart
│ │ │ ├── add_credit_card_container.dart
│ │ │ └── header_home_page.dart
│ └── utils
│ │ └── colors.dart
├── boats_challenge
│ ├── main.dart
│ ├── models
│ │ └── boat.dart
│ └── ui
│ │ ├── boat_list_page.dart
│ │ ├── boat_specs_page.dart
│ │ └── widgets
│ │ └── boat_card.dart
├── coffee_challenge
│ ├── coffee_app.dart
│ ├── model
│ │ └── coffee.dart
│ └── ui
│ │ ├── coffee_home_page.dart
│ │ ├── coffee_list_page.dart
│ │ ├── coffee_order_page.dart
│ │ └── widgets
│ │ ├── coffee_app_bar.dart
│ │ └── coffee_carousel.dart
└── main.dart
├── pubspec.lock
├── pubspec.yaml
└── test
└── widget_test.dart
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
43 | # Android Studio will place build artifacts here
44 | /android/app/debug
45 | /android/app/profile
46 | /android/app/release
47 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: d79295af24c3ed621c33713ecda14ad196fd9c31
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flutter Community Challenges
2 |
3 | Hispanic Community Flutter Challenges
4 |
5 | ## 3.- Bank Challenge
6 | | Demo |
7 | |----------------|
8 | |
9 |
10 | ## 2.- Boats Challenge
11 | Watch the live of this challenge here -> [Flutter Boats Community Challenge](https://www.youtube.com/watch?v=EEx2gSJFAPk)
12 | | Demo |
13 | |----------------|
14 | |
15 |
16 | ## 1.- Coffee Challenge
17 | Watch the live of this challenge here -> [Flutter Coffee Community Challenges](https://www.youtube.com/watch?v=myyT-4BtiD8&t=1135s)
18 | | Demo 1 | Demo 2 |
19 | |----------------|--------------|
20 | |
|
|
21 |
22 |
23 | ## Getting Started
24 |
25 | This project is a starting point for a Flutter application.
26 |
27 | A few resources to get you started if this is your first Flutter project:
28 |
29 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
30 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
31 |
32 | For help getting started with Flutter, view our
33 | [online documentation](https://flutter.dev/docs), which offers tutorials,
34 | samples, guidance on mobile development, and a full API reference.
35 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 30
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | defaultConfig {
36 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
37 | applicationId "com.brocodev.flutter_community_challenges"
38 | minSdkVersion 16
39 | targetSdkVersion 30
40 | versionCode flutterVersionCode.toInteger()
41 | versionName flutterVersionName
42 | }
43 |
44 | buildTypes {
45 | release {
46 | // TODO: Add your own signing config for the release build.
47 | // Signing with the debug keys for now, so `flutter run --release` works.
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 | }
52 |
53 | flutter {
54 | source '../..'
55 | }
56 |
57 | dependencies {
58 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
59 | }
60 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
13 |
17 |
21 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
37 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/brocodev/flutter_community_challenges/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.brocodev.flutter_community_challenges
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/android/settings_aar.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/assets/bank_challenge/img/bbva-background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/bbva-background.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/bbva-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/bbva-logo.png
--------------------------------------------------------------------------------
/assets/bank_challenge/img/citi-background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/citi-background.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/citi-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/citi-logo.png
--------------------------------------------------------------------------------
/assets/bank_challenge/img/hbo-max-logo.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/hbo-max-logo.webp
--------------------------------------------------------------------------------
/assets/bank_challenge/img/netflix-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/netflix-logo.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/red-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/red-bg.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/san-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/san-logo.png
--------------------------------------------------------------------------------
/assets/bank_challenge/img/santander-background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/santander-background.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/save-money.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/save-money.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user1.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user2.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user3.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user4.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user5.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user6.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user7.jpg
--------------------------------------------------------------------------------
/assets/bank_challenge/img/user8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/bank_challenge/img/user8.jpg
--------------------------------------------------------------------------------
/assets/boats_challenge/img/boat1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/boat1.png
--------------------------------------------------------------------------------
/assets/boats_challenge/img/boat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/boat2.png
--------------------------------------------------------------------------------
/assets/boats_challenge/img/boat3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/boat3.png
--------------------------------------------------------------------------------
/assets/boats_challenge/img/boat4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/boat4.png
--------------------------------------------------------------------------------
/assets/boats_challenge/img/gallery1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/gallery1.jpg
--------------------------------------------------------------------------------
/assets/boats_challenge/img/gallery2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/gallery2.jpg
--------------------------------------------------------------------------------
/assets/boats_challenge/img/gallery3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/gallery3.jpg
--------------------------------------------------------------------------------
/assets/boats_challenge/img/gallery4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/gallery4.jpg
--------------------------------------------------------------------------------
/assets/boats_challenge/img/gallery5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/boats_challenge/img/gallery5.jpg
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/1.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/10.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/11.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/12.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/2.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/3.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/4.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/5.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/6.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/7.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/8.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/assets/coffee_challenge/img/9.png
--------------------------------------------------------------------------------
/assets/coffee_challenge/img/names.MD:
--------------------------------------------------------------------------------
1 | # **Coffe Names**
2 |
3 | - 1. Caramel Macchiato
4 | - 2. Caramel Cold Drink
5 | - 3. Iced Coffe Mocha
6 | - 4. Caramelized Pecan Latte
7 | - 5. Toffee Nut Latte
8 | - 6. Capuchino
9 | - 7. Toffee Nut Iced Latte
10 | - 8. Americano
11 | - 9. Vietnamese-Style Iced Coffee
12 | - 10. Black Tea Latte
13 | - 11. Classic Irish Coffee
14 | - 12. Toffee Nut Crunch Latte
--------------------------------------------------------------------------------
/assets/coffee_challenge/svg/b-coffee-cup.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/coffee_challenge/svg/m-coffee-cup.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/coffee_challenge/svg/s-coffee-cup.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/ephemeral/
22 | Flutter/app.flx
23 | Flutter/app.zip
24 | Flutter/flutter_assets/
25 | Flutter/flutter_export_environment.sh
26 | ServiceDefinitions.json
27 | Runner/GeneratedPluginRegistrant.*
28 |
29 | # Exceptions to above rules.
30 | !default.mode1v3
31 | !default.mode2v3
32 | !default.pbxuser
33 | !default.perspectivev3
34 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
16 | /* End PBXBuildFile section */
17 |
18 | /* Begin PBXCopyFilesBuildPhase section */
19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
20 | isa = PBXCopyFilesBuildPhase;
21 | buildActionMask = 2147483647;
22 | dstPath = "";
23 | dstSubfolderSpec = 10;
24 | files = (
25 | );
26 | name = "Embed Frameworks";
27 | runOnlyForDeploymentPostprocessing = 0;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
45 | /* End PBXFileReference section */
46 |
47 | /* Begin PBXFrameworksBuildPhase section */
48 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
49 | isa = PBXFrameworksBuildPhase;
50 | buildActionMask = 2147483647;
51 | files = (
52 | );
53 | runOnlyForDeploymentPostprocessing = 0;
54 | };
55 | /* End PBXFrameworksBuildPhase section */
56 |
57 | /* Begin PBXGroup section */
58 | 9740EEB11CF90186004384FC /* Flutter */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
65 | );
66 | name = Flutter;
67 | sourceTree = "";
68 | };
69 | 97C146E51CF9000F007C117D = {
70 | isa = PBXGroup;
71 | children = (
72 | 9740EEB11CF90186004384FC /* Flutter */,
73 | 97C146F01CF9000F007C117D /* Runner */,
74 | 97C146EF1CF9000F007C117D /* Products */,
75 | );
76 | sourceTree = "";
77 | };
78 | 97C146EF1CF9000F007C117D /* Products */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 97C146EE1CF9000F007C117D /* Runner.app */,
82 | );
83 | name = Products;
84 | sourceTree = "";
85 | };
86 | 97C146F01CF9000F007C117D /* Runner */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
92 | 97C147021CF9000F007C117D /* Info.plist */,
93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
97 | );
98 | path = Runner;
99 | sourceTree = "";
100 | };
101 | /* End PBXGroup section */
102 |
103 | /* Begin PBXNativeTarget section */
104 | 97C146ED1CF9000F007C117D /* Runner */ = {
105 | isa = PBXNativeTarget;
106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
107 | buildPhases = (
108 | 9740EEB61CF901F6004384FC /* Run Script */,
109 | 97C146EA1CF9000F007C117D /* Sources */,
110 | 97C146EB1CF9000F007C117D /* Frameworks */,
111 | 97C146EC1CF9000F007C117D /* Resources */,
112 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
114 | );
115 | buildRules = (
116 | );
117 | dependencies = (
118 | );
119 | name = Runner;
120 | productName = Runner;
121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
122 | productType = "com.apple.product-type.application";
123 | };
124 | /* End PBXNativeTarget section */
125 |
126 | /* Begin PBXProject section */
127 | 97C146E61CF9000F007C117D /* Project object */ = {
128 | isa = PBXProject;
129 | attributes = {
130 | LastUpgradeCheck = 1020;
131 | ORGANIZATIONNAME = "";
132 | TargetAttributes = {
133 | 97C146ED1CF9000F007C117D = {
134 | CreatedOnToolsVersion = 7.3.1;
135 | LastSwiftMigration = 1100;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
140 | compatibilityVersion = "Xcode 9.3";
141 | developmentRegion = en;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | Base,
146 | );
147 | mainGroup = 97C146E51CF9000F007C117D;
148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
149 | projectDirPath = "";
150 | projectRoot = "";
151 | targets = (
152 | 97C146ED1CF9000F007C117D /* Runner */,
153 | );
154 | };
155 | /* End PBXProject section */
156 |
157 | /* Begin PBXResourcesBuildPhase section */
158 | 97C146EC1CF9000F007C117D /* Resources */ = {
159 | isa = PBXResourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
166 | );
167 | runOnlyForDeploymentPostprocessing = 0;
168 | };
169 | /* End PBXResourcesBuildPhase section */
170 |
171 | /* Begin PBXShellScriptBuildPhase section */
172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
173 | isa = PBXShellScriptBuildPhase;
174 | buildActionMask = 2147483647;
175 | files = (
176 | );
177 | inputPaths = (
178 | );
179 | name = "Thin Binary";
180 | outputPaths = (
181 | );
182 | runOnlyForDeploymentPostprocessing = 0;
183 | shellPath = /bin/sh;
184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
185 | };
186 | 9740EEB61CF901F6004384FC /* Run Script */ = {
187 | isa = PBXShellScriptBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | );
191 | inputPaths = (
192 | );
193 | name = "Run Script";
194 | outputPaths = (
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | shellPath = /bin/sh;
198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
199 | };
200 | /* End PBXShellScriptBuildPhase section */
201 |
202 | /* Begin PBXSourcesBuildPhase section */
203 | 97C146EA1CF9000F007C117D /* Sources */ = {
204 | isa = PBXSourcesBuildPhase;
205 | buildActionMask = 2147483647;
206 | files = (
207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
209 | );
210 | runOnlyForDeploymentPostprocessing = 0;
211 | };
212 | /* End PBXSourcesBuildPhase section */
213 |
214 | /* Begin PBXVariantGroup section */
215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
216 | isa = PBXVariantGroup;
217 | children = (
218 | 97C146FB1CF9000F007C117D /* Base */,
219 | );
220 | name = Main.storyboard;
221 | sourceTree = "";
222 | };
223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
224 | isa = PBXVariantGroup;
225 | children = (
226 | 97C147001CF9000F007C117D /* Base */,
227 | );
228 | name = LaunchScreen.storyboard;
229 | sourceTree = "";
230 | };
231 | /* End PBXVariantGroup section */
232 |
233 | /* Begin XCBuildConfiguration section */
234 | 249021D3217E4FDB00AE95B9 /* Profile */ = {
235 | isa = XCBuildConfiguration;
236 | buildSettings = {
237 | ALWAYS_SEARCH_USER_PATHS = NO;
238 | CLANG_ANALYZER_NONNULL = YES;
239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
240 | CLANG_CXX_LIBRARY = "libc++";
241 | CLANG_ENABLE_MODULES = YES;
242 | CLANG_ENABLE_OBJC_ARC = YES;
243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
244 | CLANG_WARN_BOOL_CONVERSION = YES;
245 | CLANG_WARN_COMMA = YES;
246 | CLANG_WARN_CONSTANT_CONVERSION = YES;
247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
249 | CLANG_WARN_EMPTY_BODY = YES;
250 | CLANG_WARN_ENUM_CONVERSION = YES;
251 | CLANG_WARN_INFINITE_RECURSION = YES;
252 | CLANG_WARN_INT_CONVERSION = YES;
253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
258 | CLANG_WARN_STRICT_PROTOTYPES = YES;
259 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
260 | CLANG_WARN_UNREACHABLE_CODE = YES;
261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
263 | COPY_PHASE_STRIP = NO;
264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
265 | ENABLE_NS_ASSERTIONS = NO;
266 | ENABLE_STRICT_OBJC_MSGSEND = YES;
267 | GCC_C_LANGUAGE_STANDARD = gnu99;
268 | GCC_NO_COMMON_BLOCKS = YES;
269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
271 | GCC_WARN_UNDECLARED_SELECTOR = YES;
272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
273 | GCC_WARN_UNUSED_FUNCTION = YES;
274 | GCC_WARN_UNUSED_VARIABLE = YES;
275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
276 | MTL_ENABLE_DEBUG_INFO = NO;
277 | SDKROOT = iphoneos;
278 | SUPPORTED_PLATFORMS = iphoneos;
279 | TARGETED_DEVICE_FAMILY = "1,2";
280 | VALIDATE_PRODUCT = YES;
281 | };
282 | name = Profile;
283 | };
284 | 249021D4217E4FDB00AE95B9 /* Profile */ = {
285 | isa = XCBuildConfiguration;
286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
287 | buildSettings = {
288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
289 | CLANG_ENABLE_MODULES = YES;
290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
291 | ENABLE_BITCODE = NO;
292 | INFOPLIST_FILE = Runner/Info.plist;
293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
294 | PRODUCT_BUNDLE_IDENTIFIER = com.brocodev.flutterCommunityChallenges;
295 | PRODUCT_NAME = "$(TARGET_NAME)";
296 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
297 | SWIFT_VERSION = 5.0;
298 | VERSIONING_SYSTEM = "apple-generic";
299 | };
300 | name = Profile;
301 | };
302 | 97C147031CF9000F007C117D /* Debug */ = {
303 | isa = XCBuildConfiguration;
304 | buildSettings = {
305 | ALWAYS_SEARCH_USER_PATHS = NO;
306 | CLANG_ANALYZER_NONNULL = YES;
307 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
308 | CLANG_CXX_LIBRARY = "libc++";
309 | CLANG_ENABLE_MODULES = YES;
310 | CLANG_ENABLE_OBJC_ARC = YES;
311 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
312 | CLANG_WARN_BOOL_CONVERSION = YES;
313 | CLANG_WARN_COMMA = YES;
314 | CLANG_WARN_CONSTANT_CONVERSION = YES;
315 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
316 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
317 | CLANG_WARN_EMPTY_BODY = YES;
318 | CLANG_WARN_ENUM_CONVERSION = YES;
319 | CLANG_WARN_INFINITE_RECURSION = YES;
320 | CLANG_WARN_INT_CONVERSION = YES;
321 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
322 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
323 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
324 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
325 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
326 | CLANG_WARN_STRICT_PROTOTYPES = YES;
327 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
328 | CLANG_WARN_UNREACHABLE_CODE = YES;
329 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
330 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
331 | COPY_PHASE_STRIP = NO;
332 | DEBUG_INFORMATION_FORMAT = dwarf;
333 | ENABLE_STRICT_OBJC_MSGSEND = YES;
334 | ENABLE_TESTABILITY = YES;
335 | GCC_C_LANGUAGE_STANDARD = gnu99;
336 | GCC_DYNAMIC_NO_PIC = NO;
337 | GCC_NO_COMMON_BLOCKS = YES;
338 | GCC_OPTIMIZATION_LEVEL = 0;
339 | GCC_PREPROCESSOR_DEFINITIONS = (
340 | "DEBUG=1",
341 | "$(inherited)",
342 | );
343 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
344 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
345 | GCC_WARN_UNDECLARED_SELECTOR = YES;
346 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
347 | GCC_WARN_UNUSED_FUNCTION = YES;
348 | GCC_WARN_UNUSED_VARIABLE = YES;
349 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
350 | MTL_ENABLE_DEBUG_INFO = YES;
351 | ONLY_ACTIVE_ARCH = YES;
352 | SDKROOT = iphoneos;
353 | TARGETED_DEVICE_FAMILY = "1,2";
354 | };
355 | name = Debug;
356 | };
357 | 97C147041CF9000F007C117D /* Release */ = {
358 | isa = XCBuildConfiguration;
359 | buildSettings = {
360 | ALWAYS_SEARCH_USER_PATHS = NO;
361 | CLANG_ANALYZER_NONNULL = YES;
362 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
363 | CLANG_CXX_LIBRARY = "libc++";
364 | CLANG_ENABLE_MODULES = YES;
365 | CLANG_ENABLE_OBJC_ARC = YES;
366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
367 | CLANG_WARN_BOOL_CONVERSION = YES;
368 | CLANG_WARN_COMMA = YES;
369 | CLANG_WARN_CONSTANT_CONVERSION = YES;
370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
372 | CLANG_WARN_EMPTY_BODY = YES;
373 | CLANG_WARN_ENUM_CONVERSION = YES;
374 | CLANG_WARN_INFINITE_RECURSION = YES;
375 | CLANG_WARN_INT_CONVERSION = YES;
376 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
377 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
378 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
380 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
381 | CLANG_WARN_STRICT_PROTOTYPES = YES;
382 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
383 | CLANG_WARN_UNREACHABLE_CODE = YES;
384 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
385 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
386 | COPY_PHASE_STRIP = NO;
387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
388 | ENABLE_NS_ASSERTIONS = NO;
389 | ENABLE_STRICT_OBJC_MSGSEND = YES;
390 | GCC_C_LANGUAGE_STANDARD = gnu99;
391 | GCC_NO_COMMON_BLOCKS = YES;
392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
394 | GCC_WARN_UNDECLARED_SELECTOR = YES;
395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
396 | GCC_WARN_UNUSED_FUNCTION = YES;
397 | GCC_WARN_UNUSED_VARIABLE = YES;
398 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
399 | MTL_ENABLE_DEBUG_INFO = NO;
400 | SDKROOT = iphoneos;
401 | SUPPORTED_PLATFORMS = iphoneos;
402 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
403 | TARGETED_DEVICE_FAMILY = "1,2";
404 | VALIDATE_PRODUCT = YES;
405 | };
406 | name = Release;
407 | };
408 | 97C147061CF9000F007C117D /* Debug */ = {
409 | isa = XCBuildConfiguration;
410 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
411 | buildSettings = {
412 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
413 | CLANG_ENABLE_MODULES = YES;
414 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
415 | ENABLE_BITCODE = NO;
416 | INFOPLIST_FILE = Runner/Info.plist;
417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
418 | PRODUCT_BUNDLE_IDENTIFIER = com.brocodev.flutterCommunityChallenges;
419 | PRODUCT_NAME = "$(TARGET_NAME)";
420 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
421 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
422 | SWIFT_VERSION = 5.0;
423 | VERSIONING_SYSTEM = "apple-generic";
424 | };
425 | name = Debug;
426 | };
427 | 97C147071CF9000F007C117D /* Release */ = {
428 | isa = XCBuildConfiguration;
429 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
430 | buildSettings = {
431 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
432 | CLANG_ENABLE_MODULES = YES;
433 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
434 | ENABLE_BITCODE = NO;
435 | INFOPLIST_FILE = Runner/Info.plist;
436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
437 | PRODUCT_BUNDLE_IDENTIFIER = com.brocodev.flutterCommunityChallenges;
438 | PRODUCT_NAME = "$(TARGET_NAME)";
439 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
440 | SWIFT_VERSION = 5.0;
441 | VERSIONING_SYSTEM = "apple-generic";
442 | };
443 | name = Release;
444 | };
445 | /* End XCBuildConfiguration section */
446 |
447 | /* Begin XCConfigurationList section */
448 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
449 | isa = XCConfigurationList;
450 | buildConfigurations = (
451 | 97C147031CF9000F007C117D /* Debug */,
452 | 97C147041CF9000F007C117D /* Release */,
453 | 249021D3217E4FDB00AE95B9 /* Profile */,
454 | );
455 | defaultConfigurationIsVisible = 0;
456 | defaultConfigurationName = Release;
457 | };
458 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
459 | isa = XCConfigurationList;
460 | buildConfigurations = (
461 | 97C147061CF9000F007C117D /* Debug */,
462 | 97C147071CF9000F007C117D /* Release */,
463 | 249021D4217E4FDB00AE95B9 /* Profile */,
464 | );
465 | defaultConfigurationIsVisible = 0;
466 | defaultConfigurationName = Release;
467 | };
468 | /* End XCConfigurationList section */
469 | };
470 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
471 | }
472 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/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/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brocodev/flutter_community_challenges/a78aa1b3b093f7e7d4b12ac3cde39c486a3b1651/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | flutter_community_challenges
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/bank_challenge/bank_challenge_app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/bank_challenge/ui/home_page.dart';
3 | import 'package:google_fonts/google_fonts.dart';
4 |
5 | class BankChallengeApp extends StatelessWidget {
6 | const BankChallengeApp({Key? key}) : super(key: key);
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | debugShowCheckedModeBanner: false,
12 | theme: ThemeData(
13 | scaffoldBackgroundColor: Colors.grey[50],
14 | textTheme: GoogleFonts.montserratTextTheme()
15 | ),
16 | home: const HomePage(),
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/bank_challenge/model/bank_models.dart:
--------------------------------------------------------------------------------
1 | //--------------------------------------------
2 | // BANK ACCOUNT MODEl
3 | //--------------------------------------------
4 | class BankAccount {
5 | const BankAccount(
6 | this.balance,
7 | this.numberCard,
8 | this.rawForegroundColor,
9 | this.bankName,
10 | this.bankLogo,
11 | this.imageBackground,
12 | this.lastTransaction,
13 | );
14 |
15 | final int numberCard;
16 | final int rawForegroundColor;
17 | final double balance;
18 | final String bankName;
19 | final String bankLogo;
20 | final String imageBackground;
21 | final AccountTransaction lastTransaction;
22 |
23 | static List get accountCards => [
24 | //First Account Card
25 | BankAccount(
26 | 10230,
27 | 9002,
28 | 0x400040FF,
29 | 'BBVA Bancomer',
30 | 'assets/bank_challenge/img/bbva-logo.png',
31 | 'assets/bank_challenge/img/bbva-background.jpg',
32 | const AccountTransaction('Next 30 July', 'HBO Max', -14.99,
33 | 'assets/bank_challenge/img/hbo-max-logo.webp'),
34 | ),
35 | //Second Account Card
36 | BankAccount(
37 | 1460,
38 | 8021,
39 | 0x40000000,
40 | 'Citi Banamex',
41 | 'assets/bank_challenge/img/citi-logo.png',
42 | 'assets/bank_challenge/img/citi-background.jpg',
43 | const AccountTransaction('Next 06 August', 'Netflix', -12.99,
44 | 'assets/bank_challenge/img/netflix-logo.jpg'),
45 | ),
46 | //Third Account Card
47 | BankAccount(
48 | 13230,
49 | 9002,
50 | 0x40FF0000,
51 | 'Santander',
52 | 'assets/bank_challenge/img/san-logo.png',
53 | 'assets/bank_challenge/img/santander-background.jpg',
54 | const AccountTransaction('June 31', 'Deposit', 320.00,
55 | 'assets/bank_challenge/img/save-money.jpg'),
56 | ),
57 | ];
58 | }
59 |
60 | //--------------------------------------------
61 | // BANK CLIENT MODEL
62 | //--------------------------------------------
63 | class BankClient {
64 | const BankClient(this.name, this.pathImage, this.accounts);
65 |
66 | final String name;
67 | final String pathImage;
68 | final List accounts;
69 |
70 | static BankClient get currentUser => BankClient(
71 | 'Matt Johnson',
72 | 'assets/bank_challenge/img/user5.jpg',
73 | BankAccount.accountCards,
74 | );
75 |
76 | static List get users => [
77 | BankClient('Francis Garcia', 'assets/bank_challenge/img/user1.jpg', []),
78 | BankClient('Arthur Li', 'assets/bank_challenge/img/user2.jpg', []),
79 | BankClient('Christian Lake', 'assets/bank_challenge/img/user3.jpg', []),
80 | BankClient('Liam Smith', 'assets/bank_challenge/img/user4.jpg', []),
81 | BankClient('Carl ', 'assets/bank_challenge/img/user6.jpg', []),
82 | BankClient('Guadalupe', 'assets/bank_challenge/img/user7.jpg', []),
83 | BankClient('Liliano', 'assets/bank_challenge/img/user8.jpg', []),
84 | ];
85 | }
86 |
87 | //--------------------------------------------
88 | // ACCOUNT TRANSACTIONS MODEL
89 | //--------------------------------------------
90 | class AccountTransaction {
91 | const AccountTransaction(
92 | this.header,
93 | this.concept,
94 | this.money,
95 | this.srcImage,
96 | );
97 |
98 | final String header;
99 | final String concept;
100 | final double money;
101 | final String srcImage;
102 | }
103 |
--------------------------------------------------------------------------------
/lib/bank_challenge/ui/home_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_community_challenges/bank_challenge/model/bank_models.dart';
5 | import 'package:flutter_community_challenges/bank_challenge/ui/widgets/add_credit_card_container.dart';
6 | import 'package:flutter_community_challenges/bank_challenge/ui/widgets/account_card.dart';
7 | import 'package:flutter_community_challenges/bank_challenge/ui/widgets/header_home_page.dart';
8 | import 'package:flutter_community_challenges/bank_challenge/utils/colors.dart';
9 |
10 | class HomePage extends StatefulWidget {
11 | const HomePage({Key? key}) : super(key: key);
12 |
13 | @override
14 | _HomePageState createState() => _HomePageState();
15 | }
16 |
17 | class _HomePageState extends State
18 | with SingleTickerProviderStateMixin {
19 | late AnimationController _controller;
20 | late PageController _pageController;
21 | late int _indexPage;
22 | late int _currentIndex;
23 | late bool _enableAddCreditCard;
24 | double _blueBgTranslatePercent = 1.0;
25 | double _blueBgTransitionPercent = 1.0;
26 | bool _hideByVelocity = false;
27 |
28 | // Data
29 | late final BankClient currentUser;
30 | late final List userAccounts;
31 | late AccountTransaction selectedLastTransaction;
32 |
33 | @override
34 | void initState() {
35 | _pageController = PageController(viewportFraction: .85, initialPage: 1)
36 | ..addListener(_pageListener);
37 | _controller = AnimationController(
38 | vsync: this, duration: const Duration(milliseconds: 600));
39 | _indexPage = 1;
40 | _currentIndex = 1;
41 | _enableAddCreditCard = false;
42 | // Data
43 | currentUser = BankClient.currentUser;
44 | userAccounts = currentUser.accounts;
45 | selectedLastTransaction = userAccounts.first.lastTransaction;
46 | super.initState();
47 | }
48 |
49 | void _pageListener() {
50 | if (_pageController.page! > 1) {
51 | _blueBgTranslatePercent = _pageController.page!;
52 | } else {
53 | _blueBgTransitionPercent = _pageController.page!;
54 | _enableAddCreditCard = (_blueBgTransitionPercent < .1);
55 | }
56 | setState(() {});
57 | }
58 |
59 | void _onPageChange(int value) {
60 | _currentIndex = value;
61 | setState(() {
62 | _indexPage = (value == 0) ? 0 : value - 1;
63 | selectedLastTransaction = userAccounts[_indexPage].lastTransaction;
64 | });
65 | }
66 |
67 | // Custom transition builder for the bottom AnimatedSwitch
68 | Widget _transitionBuilder(child, animation) {
69 | return FadeTransition(
70 | opacity: animation,
71 | child: SlideTransition(
72 | position: Tween(
73 | begin: Offset(0, 1),
74 | end: Offset(0, 0),
75 | ).animate(animation),
76 | child: child,
77 | ),
78 | );
79 | }
80 |
81 | void _onVerticalDragUpdate(DragUpdateDetails details) {
82 | if (_currentIndex > 0) {
83 | if (details.primaryDelta! > 0.0) {
84 | _controller.value += 0.004;
85 | } else {
86 | _controller.value -= 0.004;
87 | }
88 |
89 | if (details.primaryDelta! > -1.5) {
90 | _hideByVelocity = false;
91 | } else {
92 | _hideByVelocity = true;
93 | _controller.reverse();
94 | }
95 | }
96 | setState(() {});
97 | }
98 |
99 | void _onVerticalDragEnd(DragEndDetails details) {
100 | if (_currentIndex >= 0) {
101 | if (_controller.value < 0.2 || _hideByVelocity) {
102 | _controller.reverse();
103 | } else {
104 | _controller.forward();
105 | }
106 | }
107 | }
108 |
109 | @override
110 | Widget build(BuildContext context) {
111 | return Scaffold(
112 | body: SafeArea(
113 | child: AnimatedBuilder(
114 | animation: _controller,
115 | builder: (_, __) {
116 | final value = _controller.value;
117 | return GestureDetector(
118 | onVerticalDragUpdate: _onVerticalDragUpdate,
119 | onVerticalDragEnd: _onVerticalDragEnd,
120 | child: Container(
121 | color: Colors.transparent,
122 | child: Column(
123 | children: [
124 | //-------------------------------------
125 | // Header Home Page Widget
126 | //-------------------------------------
127 | Expanded(
128 | flex: 4,
129 | child: HeaderHomePage(
130 | expandedFactor: 1 - value,
131 | ),
132 | ),
133 | Expanded(
134 | flex: 10,
135 | child: LayoutBuilder(builder: (context, constraints) {
136 | final widthBlueCard = constraints.maxWidth - 60;
137 | final heightBlueCard = constraints.maxHeight - 40;
138 | return Transform.translate(
139 | offset:
140 | Offset(0, (constraints.maxHeight * 2) * value),
141 | child: Stack(
142 | children: [
143 | //-------------------------------------
144 | // Add Credit Card Background
145 | //-------------------------------------
146 | Transform.translate(
147 | offset: Offset(
148 | -widthBlueCard *
149 | (_blueBgTranslatePercent - 1),
150 | 0),
151 | child: AddCreditCardContainer(
152 | percent: _blueBgTransitionPercent,
153 | height: heightBlueCard,
154 | width: widthBlueCard,
155 | showItems: _enableAddCreditCard,
156 | ),
157 | ),
158 | //-------------------------------------
159 | // Account Cards Page View
160 | //-------------------------------------
161 | Transform(
162 | transform: Matrix4.identity()
163 | ..translate(
164 | 100.0 * (1 - _blueBgTransitionPercent)),
165 | child: PageView.builder(
166 | onPageChanged: _onPageChange,
167 | itemCount: userAccounts.length + 1,
168 | physics: const BouncingScrollPhysics(),
169 | controller: _pageController,
170 | itemBuilder: (context, index) {
171 | if (index == 0) {
172 | return const SizedBox();
173 | } else {
174 | final account = userAccounts[index - 1];
175 | return Padding(
176 | padding: const EdgeInsets.symmetric(
177 | horizontal: 10),
178 | child: AccountCard(account: account),
179 | );
180 | }
181 | },
182 | ),
183 | ),
184 | ],
185 | ),
186 | );
187 | }),
188 | ),
189 | //-------------------------------------
190 | // Animated Transaction Widget
191 | //-------------------------------------
192 | Expanded(
193 | flex: 2,
194 | child: LayoutBuilder(builder: (context, constraints) {
195 | return Transform.translate(
196 | offset:
197 | Offset(0, (constraints.maxHeight * 4) * value),
198 | child: Padding(
199 | padding:
200 | const EdgeInsets.fromLTRB(30, 30, 30, 10),
201 | child: Opacity(
202 | opacity: _blueBgTransitionPercent,
203 | child: AnimatedSwitcher(
204 | duration: kThemeChangeDuration,
205 | transitionBuilder: _transitionBuilder,
206 | child: _TransactionRow(
207 | key: Key(_indexPage.toString()),
208 | transaction: selectedLastTransaction,
209 | ),
210 | ),
211 | ),
212 | ),
213 | );
214 | }),
215 | ),
216 | ],
217 | ),
218 | ),
219 | );
220 | }),
221 | ),
222 | );
223 | }
224 | }
225 |
226 | class _TransactionRow extends StatelessWidget {
227 | const _TransactionRow({
228 | Key? key,
229 | required this.transaction,
230 | }) : super(key: key);
231 |
232 | final AccountTransaction transaction;
233 |
234 | @override
235 | Widget build(BuildContext context) {
236 | return Row(
237 | children: [
238 | AspectRatio(
239 | aspectRatio: 1,
240 | child: ClipRRect(
241 | borderRadius: BorderRadius.circular(15),
242 | child: Image.asset(
243 | transaction.srcImage,
244 | fit: BoxFit.cover,
245 | ),
246 | ),
247 | ),
248 | const SizedBox(width: 20),
249 | Expanded(
250 | child: Column(
251 | crossAxisAlignment: CrossAxisAlignment.start,
252 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
253 | children: [
254 | Text(
255 | transaction.header,
256 | style: TextStyle(
257 | color: Colors.grey,
258 | fontWeight: FontWeight.bold,
259 | ),
260 | ),
261 | Text(
262 | transaction.concept,
263 | style: TextStyle(
264 | color: BankColors.kTextColor,
265 | fontWeight: FontWeight.bold,
266 | fontSize: 16,
267 | ),
268 | ),
269 | ],
270 | ),
271 | ),
272 | Text(
273 | '\$${transaction.money}',
274 | style: TextStyle(
275 | color: BankColors.kTextColor,
276 | fontWeight: FontWeight.bold,
277 | fontSize: 18,
278 | ),
279 | )
280 | ],
281 | );
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/lib/bank_challenge/ui/widgets/account_card.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/bank_challenge/model/bank_models.dart';
3 |
4 | class AccountCard extends StatelessWidget {
5 | const AccountCard({
6 | Key? key,
7 | required this.account,
8 | }) : super(key: key);
9 |
10 | final BankAccount account;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | final foregroundColor = Color(account.rawForegroundColor);
15 |
16 | return Container(
17 | // margin: const EdgeInsets.symmetric(horizontal: 10),
18 | padding: const EdgeInsets.all(20),
19 | decoration: BoxDecoration(
20 | borderRadius: BorderRadius.circular(30.0),
21 | image: DecorationImage(
22 | image: AssetImage(account.imageBackground),
23 | fit: BoxFit.cover,
24 | ),
25 | ),
26 | child: Column(
27 | crossAxisAlignment: CrossAxisAlignment.start,
28 | children: [
29 | Row(
30 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
31 | children: [
32 | Image.asset(
33 | account.bankLogo,
34 | width: 60,
35 | color: foregroundColor,
36 | ),
37 | Text(
38 | account.numberCard.toString(),
39 | style: TextStyle(
40 | fontSize: 24,
41 | color: foregroundColor,
42 | fontWeight: FontWeight.w500,
43 | ),
44 | )
45 | ],
46 | ),
47 | const Spacer(),
48 | Text(
49 | '\$${account.balance}',
50 | style: TextStyle(
51 | fontSize: 28,
52 | color: Color(0xFF081A38),
53 | fontWeight: FontWeight.w600,
54 | ),
55 | )
56 | ],
57 | ),
58 | );
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/lib/bank_challenge/ui/widgets/add_credit_card_container.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_community_challenges/bank_challenge/utils/colors.dart';
4 |
5 | class AddCreditCardContainer extends StatelessWidget {
6 | const AddCreditCardContainer({
7 | Key? key,
8 | required this.percent,
9 | required this.height,
10 | required this.width,
11 | required this.showItems,
12 | }) : super(key: key);
13 |
14 | final double percent;
15 | final double height;
16 | final double width;
17 | final bool showItems;
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | final size = MediaQuery.of(context).size;
22 | return OverflowBox(
23 | maxHeight: size.height,
24 | maxWidth: size.width + 10,
25 | alignment:
26 | Alignment.lerp(Alignment(0, .385), Alignment(-.52, 0), percent)!,
27 | child: Container(
28 | height: lerpDouble(size.height + 100, height, percent),
29 | width: lerpDouble(size.width + 10, width, percent),
30 | decoration: BoxDecoration(
31 | color: BankColors.kDarkBlue,
32 | borderRadius: BorderRadius.circular(30 * percent),
33 | ),
34 | child: AnimatedSwitcher(
35 | duration: kThemeChangeDuration,
36 | child: showItems
37 | ? Column(
38 | children: [
39 | Expanded(
40 | flex: 5,
41 | child: const _HeaderAddCreditCard(),
42 | ),
43 | Expanded(
44 | flex: 1,
45 | child: Text(
46 | 'Your card number',
47 | style: TextStyle(
48 | fontSize: 18,
49 | fontWeight: FontWeight.bold,
50 | color: BankColors.kLessDarkBlue,
51 | ),
52 | ),
53 | ),
54 | Expanded(
55 | flex: 10,
56 | child: GridView.builder(
57 | physics: const NeverScrollableScrollPhysics(),
58 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
59 | crossAxisCount: 3,
60 | mainAxisExtent: 100,
61 | childAspectRatio: 1,
62 | ),
63 | itemCount: 12,
64 | itemBuilder: (context, index) {
65 | final style = TextStyle(
66 | fontWeight: FontWeight.bold,
67 | color: Colors.white,
68 | fontSize: 24);
69 |
70 | switch (index) {
71 | case 9:
72 | return const Icon(
73 | Icons.qr_code_sharp,
74 | color: Colors.white,
75 | size: 28,
76 | );
77 | case 10:
78 | return Center(child: Text('0', style: style));
79 | case 11:
80 | return const Icon(
81 | Icons.backspace_outlined,
82 | color: Colors.white,
83 | size: 28,
84 | );
85 | }
86 | return Center(
87 | child: Text(
88 | '${index + 1}',
89 | style: style,
90 | ),
91 | );
92 | },
93 | ),
94 | ),
95 | const Spacer(flex: 2)
96 | ],
97 | )
98 | : const SizedBox(),
99 | ),
100 | ),
101 | );
102 | }
103 | }
104 |
105 | class _HeaderAddCreditCard extends StatelessWidget {
106 | const _HeaderAddCreditCard({
107 | Key? key,
108 | }) : super(key: key);
109 |
110 | @override
111 | Widget build(BuildContext context) {
112 | return Container(
113 | margin: const EdgeInsets.all(40.0),
114 | padding: const EdgeInsets.symmetric(horizontal: 40),
115 | decoration: BoxDecoration(
116 | color: BankColors.kSecondaryDarkBlue,
117 | borderRadius: BorderRadius.circular(30)),
118 | child: Column(
119 | mainAxisAlignment: MainAxisAlignment.spaceEvenly,
120 | children: [
121 | Row(
122 | children: [
123 | Icon(
124 | Icons.credit_card,
125 | color: Colors.white,
126 | size: 20,
127 | ),
128 | const SizedBox(width: 10),
129 | Text(
130 | 'Credit Card',
131 | style: TextStyle(
132 | fontWeight: FontWeight.bold,
133 | color: Colors.white,
134 | fontSize: 14),
135 | )
136 | ],
137 | ),
138 | Row(
139 | children: [
140 | Icon(
141 | Icons.credit_card,
142 | color: Colors.white,
143 | size: 20,
144 | ),
145 | const SizedBox(width: 10),
146 | Text(
147 | 'Open an account',
148 | style: TextStyle(
149 | fontWeight: FontWeight.bold,
150 | color: Colors.white,
151 | fontSize: 14),
152 | ),
153 | const Spacer(),
154 | Align(
155 | widthFactor: .2,
156 | child: CircleAvatar(
157 | radius: 12,
158 | ),
159 | ),
160 | CircleAvatar(
161 | radius: 12,
162 | backgroundColor: Colors.white,
163 | child: Icon(
164 | Icons.credit_card,
165 | size: 14,
166 | color: BankColors.kLessDarkBlue,
167 | ),
168 | )
169 | ],
170 | ),
171 | ],
172 | ),
173 | );
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/lib/bank_challenge/ui/widgets/header_home_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/bank_challenge/model/bank_models.dart';
3 | import 'package:flutter_community_challenges/bank_challenge/utils/colors.dart';
4 |
5 | class HeaderHomePage extends StatelessWidget {
6 | const HeaderHomePage({
7 | Key? key,
8 | required this.expandedFactor,
9 | }) : super(key: key);
10 |
11 | final double expandedFactor;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | final user = BankClient.currentUser;
16 | final size = MediaQuery.of(context).size;
17 |
18 | return OverflowBox(
19 | maxHeight: size.height,
20 | maxWidth: size.width,
21 | alignment: Alignment.topCenter,
22 | child: Stack(
23 | children: [
24 | Positioned(
25 | top: 0,
26 | left: 30 * expandedFactor,
27 | right: 30 * expandedFactor,
28 | bottom: (size.height * .8) * expandedFactor,
29 | child: Container(
30 | padding: const EdgeInsets.all(20),
31 | alignment: Alignment.topCenter,
32 | decoration: BoxDecoration(
33 | color: Colors.blueGrey[50],
34 | borderRadius: BorderRadius.circular(30 * expandedFactor),
35 | ),
36 | ),
37 | ),
38 | // Hide Animated items
39 | Positioned(
40 | left: 30,
41 | right: 30,
42 | top: 30,
43 | child: Column(
44 | children: [
45 | Padding(
46 | padding: EdgeInsets.all(20 * expandedFactor),
47 | child: _GreetingWidget(user: user),
48 | ),
49 | AnimatedSwitcher(
50 | duration: const Duration(milliseconds: 400),
51 | child: (expandedFactor < .2)
52 | ? Column(
53 | children: const [
54 | SizedBox(height: 40),
55 | SizedBox(height: 120, child: _BankUserList()),
56 | SizedBox(height: 20),
57 | _HolidayGoalWidget(),
58 | SizedBox(height: 20),
59 | _PlayServicesCard()
60 | ],
61 | )
62 | : const SizedBox(),
63 | ),
64 | ],
65 | ),
66 | ),
67 | //-------------------
68 | // Separator
69 | //-------------------
70 | // Container(
71 | // height: 8,
72 | // width: 60,
73 | // margin: const EdgeInsets.symmetric(vertical: 15),
74 | // decoration: BoxDecoration(
75 | // color: Colors.blueGrey[50],
76 | // borderRadius: BorderRadius.circular(30),
77 | // ),
78 | // )
79 | ],
80 | ),
81 | );
82 | }
83 | }
84 |
85 | class _PlayServicesCard extends StatelessWidget {
86 | const _PlayServicesCard({
87 | Key? key,
88 | }) : super(key: key);
89 |
90 | @override
91 | Widget build(BuildContext context) {
92 | return Container(
93 | height: 200,
94 | decoration: BoxDecoration(
95 | color: Colors.white,
96 | borderRadius: BorderRadius.circular(20.0),
97 | ),
98 | );
99 | }
100 | }
101 |
102 | class _HolidayGoalWidget extends StatelessWidget {
103 | const _HolidayGoalWidget({
104 | Key? key,
105 | }) : super(key: key);
106 |
107 | @override
108 | Widget build(BuildContext context) {
109 | return Container(
110 | height: 120,
111 | decoration: BoxDecoration(
112 | color: Colors.blue[100],
113 | borderRadius: BorderRadius.circular(20),
114 | ),
115 | child: Row(
116 | children: [
117 | Expanded(
118 | child: Container(
119 | margin: const EdgeInsets.all(20),
120 | decoration: BoxDecoration(
121 | color: Colors.white,
122 | borderRadius: BorderRadius.circular(15.0)),
123 | ),
124 | ),
125 | Expanded(
126 | flex: 2,
127 | child: Column(
128 | crossAxisAlignment: CrossAxisAlignment.start,
129 | children: [
130 | const SizedBox(height: 10),
131 | Chip(
132 | label: Text('Holiday goal'),
133 | labelStyle: TextStyle(
134 | color: Colors.white,
135 | fontWeight: FontWeight.bold,
136 | ),
137 | backgroundColor: Colors.blue[200],
138 | ),
139 | Text.rich(
140 | TextSpan(text: '\$ 100.00', children: [
141 | TextSpan(
142 | text: ' \$ 5000.00',
143 | style: TextStyle(
144 | color: Colors.blueGrey[400],
145 | ),
146 | )
147 | ]),
148 | style: TextStyle(
149 | fontSize: 18,
150 | color: Colors.blueGrey[900],
151 | fontWeight: FontWeight.bold,
152 | )),
153 | ],
154 | ),
155 | )
156 | ],
157 | ),
158 | );
159 | }
160 | }
161 |
162 | class _BankUserList extends StatelessWidget {
163 | const _BankUserList({
164 | Key? key,
165 | }) : super(key: key);
166 |
167 | @override
168 | Widget build(BuildContext context) {
169 | return ListView.builder(
170 | padding: const EdgeInsets.symmetric(horizontal: 20),
171 | itemCount: BankClient.users.length,
172 | itemExtent: 90,
173 | scrollDirection: Axis.horizontal,
174 | itemBuilder: (context, index) {
175 | final bankUser = BankClient.users[index];
176 | return Column(
177 | children: [
178 | CircleAvatar(
179 | radius: 30,
180 | backgroundImage: AssetImage(bankUser.pathImage),
181 | ),
182 | Text('${bankUser.name.split(' ').first}'),
183 | ],
184 | );
185 | },
186 | );
187 | }
188 | }
189 |
190 | class _GreetingWidget extends StatelessWidget {
191 | const _GreetingWidget({
192 | Key? key,
193 | required this.user,
194 | }) : super(key: key);
195 |
196 | final BankClient user;
197 |
198 | @override
199 | Widget build(BuildContext context) {
200 | return Row(
201 | mainAxisSize: MainAxisSize.min,
202 | children: [
203 | Text.rich(
204 | TextSpan(
205 | text: 'Hello',
206 | children: [
207 | TextSpan(
208 | text: ' ${user.name.split(' ').first}',
209 | style: TextStyle(fontWeight: FontWeight.bold)),
210 | ],
211 | ),
212 | style: TextStyle(fontSize: 30, color: BankColors.kTextColor),
213 | ),
214 | const Spacer(),
215 | Align(
216 | widthFactor: .2,
217 | child: CircleAvatar(
218 | radius: 30,
219 | backgroundImage: AssetImage(user.pathImage),
220 | ),
221 | ),
222 | Container(
223 | width: 60,
224 | height: 60,
225 | decoration: BoxDecoration(
226 | shape: BoxShape.circle,
227 | color: Colors.white,
228 | ),
229 | child: Icon(
230 | Icons.credit_card,
231 | color: BankColors.kLessDarkBlue,
232 | ),
233 | )
234 | ],
235 | );
236 | }
237 | }
238 |
--------------------------------------------------------------------------------
/lib/bank_challenge/utils/colors.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class BankColors {
4 | static const Color kTextColor = Color(0xFF081A38);
5 | static const Color kDarkBlue = Color(0xff0c0c32);
6 | static const Color kSecondaryDarkBlue = Color(0xff0e0e39);
7 | static const Color kLessDarkBlue = Color(0xff16165a);
8 | }
9 |
--------------------------------------------------------------------------------
/lib/boats_challenge/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/boats_challenge/ui/boat_list_page.dart';
3 |
4 | class BoatsChallengeApp extends StatelessWidget {
5 | const BoatsChallengeApp();
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | return MaterialApp(
10 | title: 'Material App',
11 | debugShowCheckedModeBanner: false,
12 | theme: ThemeData(
13 | scaffoldBackgroundColor: Colors.white,
14 | textTheme: TextTheme(
15 | headline4: TextStyle(
16 | fontSize: 32,
17 | color: Colors.grey[800],
18 | ),
19 | bodyText2: TextStyle(
20 | fontSize: 16,
21 | ),
22 | ),
23 | ),
24 | home: const BoatListPage(),
25 | );
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/boats_challenge/models/boat.dart:
--------------------------------------------------------------------------------
1 | class Boat {
2 | const Boat({
3 | required this.model,
4 | required this.owner,
5 | required this.description,
6 | required this.specs,
7 | required this.gallery,
8 | required this.imagePath,
9 | });
10 |
11 | final String model;
12 | final String owner;
13 | final String description;
14 | final Map specs;
15 | final List gallery;
16 | final String imagePath;
17 |
18 |
19 | static const _description = "Cum agripeta cantare, omnes humani generises transferre fatalis, gratis gloses.";
20 | static const _gallery = [
21 | "assets/boats_challenge/img/gallery1.jpg",
22 | "assets/boats_challenge/img/gallery2.jpg",
23 | "assets/boats_challenge/img/gallery3.jpg",
24 | "assets/boats_challenge/img/gallery4.jpg",
25 | "assets/boats_challenge/img/gallery5.jpg",
26 | ];
27 | static const _specs = {
28 | "Boat Length": "24'2",
29 | "Beam": "102'",
30 | "Weight": "2765 KG",
31 | "Fuel Capacity": "322 L"
32 | };
33 | static const listBoats = [
34 | Boat(
35 | model: "XCLR8 Speed",
36 | owner: "Tennison",
37 | imagePath: "assets/boats_challenge/img/boat1.png",
38 | description: _description,
39 | gallery: _gallery,
40 | specs: _specs),
41 |
42 | Boat(
43 | model: "X-FORCE",
44 | owner: "W - Wilson",
45 | imagePath: "assets/boats_challenge/img/boat2.png",
46 | description: _description,
47 | gallery: _gallery,
48 | specs: _specs),
49 |
50 | Boat(
51 | model: "X12 Force",
52 | owner: "Mastercraft",
53 | imagePath: "assets/boats_challenge/img/boat3.png",
54 | description: _description,
55 | gallery: _gallery,
56 | specs: _specs),
57 |
58 | Boat(
59 | model: "X21 Strength",
60 | owner: "NeoCraft",
61 | imagePath: "assets/boats_challenge/img/boat4.png",
62 | description: _description,
63 | gallery: _gallery,
64 | specs: _specs),
65 | ];
66 | }
67 |
--------------------------------------------------------------------------------
/lib/boats_challenge/ui/boat_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/boats_challenge/models/boat.dart';
3 | import 'package:flutter_community_challenges/boats_challenge/ui/widgets/boat_card.dart';
4 |
5 | import 'boat_specs_page.dart';
6 |
7 | class BoatListPage extends StatefulWidget {
8 | const BoatListPage({Key? key}) : super(key: key);
9 |
10 | @override
11 | _BoatListPageState createState() => _BoatListPageState();
12 | }
13 |
14 | class _BoatListPageState extends State {
15 | late PageController _pageController;
16 | late ValueNotifier _pageNotifier;
17 | late ValueNotifier _hideAppBarNotifier;
18 |
19 | @override
20 | void initState() {
21 | _pageController = PageController(viewportFraction: .7);
22 | _pageController.addListener(_pageListener);
23 | _pageNotifier = ValueNotifier(0.0);
24 | _hideAppBarNotifier = ValueNotifier(false);
25 | super.initState();
26 | }
27 |
28 | @override
29 | void dispose() {
30 | _pageController.removeListener(_pageListener);
31 | _pageController.dispose();
32 | super.dispose();
33 | }
34 |
35 | void _pageListener() {
36 | _pageNotifier.value = _pageController.page!;
37 | }
38 |
39 | //------------------------------------
40 | // Open Specs Boat Page
41 | //------------------------------------
42 | void _openSpecsPage(BuildContext context, Boat boat) async {
43 | _hideAppBarNotifier.value = true;
44 | await Navigator.push(
45 | context,
46 | PageRouteBuilder(
47 | reverseTransitionDuration: const Duration(milliseconds: 600),
48 | transitionDuration: const Duration(milliseconds: 600),
49 | pageBuilder: (context, animation, secondaryAnimation) {
50 | return FadeTransition(
51 | opacity: animation,
52 | child: BoatSpecsPage(boat: boat),
53 | );
54 | },
55 | ));
56 | _hideAppBarNotifier.value = false;
57 | }
58 |
59 | @override
60 | Widget build(BuildContext context) {
61 | return Scaffold(
62 | body: Column(
63 | children: [
64 | //-----------------------------------
65 | // Custom App Bar
66 | //-----------------------------------
67 | SafeArea(
68 | child: ValueListenableBuilder(
69 | valueListenable: _hideAppBarNotifier,
70 | builder: (context, value, _) {
71 | return _AnimatedCustomAppBar(animate: value);
72 | }),
73 | ),
74 | const SizedBox(height: 20),
75 | //------------------------------------
76 | // Boat Page View
77 | //------------------------------------
78 | Expanded(
79 | child: PageView.builder(
80 | controller: _pageController,
81 | physics: const BouncingScrollPhysics(),
82 | itemCount: Boat.listBoats.length,
83 | itemBuilder: (context, index) {
84 | final boat = Boat.listBoats[index];
85 | return ValueListenableBuilder(
86 | valueListenable: _pageNotifier,
87 | builder: (context, value, _) {
88 | final factorChange = (value - index).abs();
89 | return BoatCard(
90 | boat: boat,
91 | onTapSpec: () => _openSpecsPage(context, boat),
92 | factorChange: factorChange,
93 | );
94 | });
95 | }),
96 | ),
97 | ],
98 | ),
99 | );
100 | }
101 | }
102 |
103 | class _AnimatedCustomAppBar extends StatelessWidget {
104 | const _AnimatedCustomAppBar({
105 | Key? key,
106 | required this.animate,
107 | }) : super(key: key);
108 |
109 | final bool animate;
110 |
111 | @override
112 | Widget build(BuildContext context) {
113 | return AnimatedContainer(
114 | curve: Curves.fastOutSlowIn,
115 | duration: const Duration(milliseconds: 600),
116 | transform: Matrix4.translationValues(0, animate ? -100 : 0, 0),
117 | child: AnimatedOpacity(
118 | curve: Curves.fastOutSlowIn,
119 | duration: const Duration(milliseconds: 600),
120 | opacity: animate ? 0 : 1,
121 | child: SizedBox(
122 | height: kToolbarHeight,
123 | child: Padding(
124 | padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
125 | child: Row(
126 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
127 | children: [
128 | Text(
129 | "Boats",
130 | style: Theme.of(context)
131 | .textTheme
132 | .headline4!
133 | .copyWith(fontWeight: FontWeight.w500),
134 | ),
135 | IconButton(
136 | icon: Icon(Icons.search),
137 | onPressed: () {},
138 | color: Colors.grey[800],
139 | iconSize: 40,
140 | )
141 | ],
142 | ),
143 | ),
144 | ),
145 | ),
146 | );
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/lib/boats_challenge/ui/boat_specs_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:math';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_community_challenges/boats_challenge/models/boat.dart';
5 |
6 | class BoatSpecsPage extends StatelessWidget {
7 | const BoatSpecsPage({Key? key, required this.boat}) : super(key: key);
8 |
9 | final Boat boat;
10 |
11 | final _angleRotateBoat = (pi * -.5);
12 | final _dxTranslate = 80.0;
13 | final _dyTranslate = -100.0;
14 |
15 | //-------------------------------------------------
16 | // Custom Flight Hero
17 | //-------------------------------------------------
18 | Widget _flightShuttleBuilder(
19 | Animation animation, HeroFlightDirection flightDirection) {
20 | final isPop = flightDirection == HeroFlightDirection.pop;
21 | return AnimatedBuilder(
22 | animation: animation,
23 | builder: (context, child) {
24 | final value = isPop
25 | ? Curves.easeInBack.transform(animation.value)
26 | : Curves.easeOutBack.transform(animation.value);
27 | return Transform(
28 | alignment: Alignment.center,
29 | transform: Matrix4.identity()
30 | ..translate(_dxTranslate * value, _dyTranslate * value, 0)
31 | ..rotateZ(_angleRotateBoat * value),
32 | child: child,
33 | );
34 | },
35 | child: _ImageBoat(
36 | boatImagePath: boat.imagePath,
37 | ),
38 | );
39 | }
40 |
41 | @override
42 | Widget build(BuildContext context) {
43 | final animateItemNotifier = ValueNotifier(false);
44 | WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
45 | animateItemNotifier.value = true;
46 | });
47 | return Scaffold(
48 | body: Stack(
49 | children: [
50 | SingleChildScrollView(
51 | padding: const EdgeInsets.only(left: 20),
52 | physics: const BouncingScrollPhysics(),
53 | child: Column(
54 | crossAxisAlignment: CrossAxisAlignment.start,
55 | children: [
56 | //--------------------------------------
57 | // Boat Model Image
58 | //--------------------------------------
59 | Hero(
60 | tag: boat.model,
61 | flightShuttleBuilder:
62 | (_, animation, flightDirection, ___, ____) {
63 | return _flightShuttleBuilder(animation, flightDirection);
64 | },
65 | child: Transform(
66 | alignment: Alignment.center,
67 | transform: Matrix4.identity()
68 | ..translate(_dxTranslate, _dyTranslate, 0)
69 | ..rotateZ(_angleRotateBoat),
70 | child: _ImageBoat(
71 | boatImagePath: boat.imagePath,
72 | ),
73 | ),
74 | ),
75 | Transform.translate(
76 | offset: Offset(0, -MediaQuery.of(context).size.height * .32),
77 | child: Column(
78 | crossAxisAlignment: CrossAxisAlignment.start,
79 | children: [
80 | Text(
81 | boat.model,
82 | style: Theme.of(context).textTheme.headline4,
83 | ),
84 | //------------------------------
85 | // Owner boat
86 | //------------------------------
87 | Text.rich(
88 | TextSpan(
89 | text: 'By ',
90 | children: [
91 | TextSpan(
92 | text: boat.owner,
93 | style: TextStyle(
94 | color: Colors.grey[900],
95 | ),
96 | ),
97 | ],
98 | style: TextStyle(
99 | color: Colors.grey[600],
100 | height: 1.5,
101 | ),
102 | ),
103 | ),
104 | //-----------------------------------------
105 | // Animated Items
106 | //-----------------------------------------
107 | ValueListenableBuilder(
108 | valueListenable: animateItemNotifier,
109 | builder: (context, value, child) {
110 | return TweenAnimationBuilder(
111 | curve: Curves.fastOutSlowIn,
112 | tween: Tween(begin: 1.0, end: value ? 0.0 : 1.0),
113 | duration: const Duration(milliseconds: 600),
114 | builder: (context, value, child) {
115 | return Transform.translate(
116 | offset: Offset(0, (-50.0 * value)),
117 | child: Opacity(
118 | opacity: 1 - value,
119 | child: child,
120 | ),
121 | );
122 | },
123 | child: child);
124 | },
125 | child: Column(
126 | crossAxisAlignment: CrossAxisAlignment.start,
127 | children: [
128 | //------------------------------------
129 | // Description Boat
130 | //------------------------------------
131 | const SizedBox(height: 20),
132 | Text(
133 | boat.description,
134 | style: TextStyle(
135 | fontWeight: FontWeight.w300,
136 | ),
137 | ),
138 | //------------------------------------
139 | // SPECS
140 | //------------------------------------
141 | const SizedBox(height: 30),
142 | Text(
143 | 'SPECS',
144 | style: TextStyle(
145 | fontSize: 18,
146 | fontWeight: FontWeight.w300,
147 | ),
148 | ),
149 | const SizedBox(height: 10),
150 | _BoatSpecsList(boat: boat),
151 | //-------------------------------------
152 | // Gallery List View
153 | //-------------------------------------
154 | const SizedBox(height: 20),
155 | Text(
156 | 'GALLERY',
157 | style: TextStyle(
158 | fontSize: 18,
159 | fontWeight: FontWeight.w300,
160 | ),
161 | ),
162 | const SizedBox(height: 10),
163 | SizedBox(
164 | height: 200.0,
165 | child: ListView.builder(
166 | itemCount: boat.gallery.length,
167 | scrollDirection: Axis.horizontal,
168 | itemExtent: 220,
169 | physics: const BouncingScrollPhysics(),
170 | itemBuilder: (context, index) {
171 | final galleryPath = boat.gallery[index];
172 | //----------------------------------------
173 | // Gallery Image
174 | //----------------------------------------
175 | return Container(
176 | margin: const EdgeInsets.only(right: 20),
177 | clipBehavior: Clip.antiAlias,
178 | decoration: BoxDecoration(
179 | borderRadius:
180 | BorderRadius.circular(20)),
181 | child: Image.asset(
182 | galleryPath,
183 | fit: BoxFit.cover,
184 | ),
185 | );
186 | },
187 | ),
188 | ),
189 | ],
190 | ),
191 | ),
192 | ],
193 | ),
194 | )
195 | ],
196 | ),
197 | ),
198 | //--------------------------------------
199 | // Close Button
200 | //--------------------------------------
201 | Align(
202 | alignment: Alignment(-.9, -.9),
203 | child: FloatingActionButton(
204 | mini: true,
205 | backgroundColor: Colors.black12,
206 | child: Icon(Icons.close),
207 | onPressed: () {
208 | animateItemNotifier.value = false;
209 | Navigator.pop(context);
210 | },
211 | ),
212 | )
213 | ],
214 | ),
215 | );
216 | }
217 | }
218 |
219 | class _BoatSpecsList extends StatelessWidget {
220 | const _BoatSpecsList({
221 | Key? key,
222 | required this.boat,
223 | }) : super(key: key);
224 |
225 | final Boat boat;
226 |
227 | @override
228 | Widget build(BuildContext context) {
229 | return Column(
230 | children: List.generate(
231 | boat.specs.length,
232 | (index) {
233 | final key = boat.specs.keys.toList()[index];
234 | return Padding(
235 | padding: const EdgeInsets.symmetric(vertical: 10),
236 | child: Row(
237 | children: [
238 | Expanded(child: Text(key)),
239 | Expanded(
240 | child: Text(
241 | boat.specs[key]!,
242 | textAlign: TextAlign.left,
243 | style: TextStyle(
244 | fontWeight: FontWeight.w300,
245 | ),
246 | ),
247 | ),
248 | ],
249 | ),
250 | );
251 | },
252 | ),
253 | );
254 | }
255 | }
256 |
257 | class _ImageBoat extends StatelessWidget {
258 | const _ImageBoat({
259 | Key? key,
260 | required this.boatImagePath,
261 | }) : super(key: key);
262 |
263 | final String boatImagePath;
264 |
265 | @override
266 | Widget build(BuildContext context) {
267 | return AspectRatio(
268 | aspectRatio: .85,
269 | child: Image.asset(boatImagePath),
270 | );
271 | }
272 | }
273 |
--------------------------------------------------------------------------------
/lib/boats_challenge/ui/widgets/boat_card.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_community_challenges/boats_challenge/models/boat.dart';
4 |
5 | class BoatCard extends StatelessWidget {
6 | const BoatCard({
7 | Key? key,
8 | required this.boat,
9 | required this.factorChange,
10 | required this.onTapSpec,
11 | }) : super(key: key);
12 |
13 | final Boat boat;
14 | final double factorChange;
15 | final VoidCallback onTapSpec;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return Opacity(
20 | opacity: (1 - factorChange).clamp(0.0, 1.0),
21 | child: Column(
22 | children: [
23 | //-----------------------------
24 | // Image boat
25 | //-----------------------------
26 | Expanded(
27 | child: Transform.scale(
28 | alignment: Alignment(0, .5),
29 | scale: lerpDouble(1.0, 0.7, factorChange)!,
30 | child: Hero(
31 | tag: boat.model,
32 | child: Image.asset(boat.imagePath),
33 | ),
34 | ),
35 | ),
36 | const SizedBox(height: 10),
37 | Text(
38 | boat.model,
39 | style: Theme.of(context).textTheme.headline4,
40 | ),
41 | //------------------------------
42 | // Owner boat
43 | //------------------------------
44 | Text.rich(
45 | TextSpan(
46 | text: 'By ',
47 | children: [
48 | TextSpan(
49 | text: boat.owner,
50 | style: TextStyle(
51 | color: Colors.grey[900],
52 | ),
53 | ),
54 | ],
55 | style: TextStyle(color: Colors.grey[600], height: 1),
56 | ),
57 | ),
58 | //-----------------------------
59 | // See Specs Button
60 | //-----------------------------
61 | TextButton.icon(
62 | label: Icon(
63 | Icons.arrow_forward_ios_outlined,
64 | size: 16,
65 | ),
66 | icon: Text('SPEC'),
67 | onPressed: onTapSpec,
68 | style: ButtonStyle(
69 | foregroundColor: MaterialStateProperty.all(
70 | Colors.blue[900]!,
71 | ),
72 | ),
73 | ),
74 | const SizedBox(height: 40),
75 | ],
76 | ),
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/coffee_app.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_community_challenges/coffee_challenge/ui/coffee_home_page.dart';
3 | import 'package:google_fonts/google_fonts.dart';
4 |
5 | class CoffeeChallengeApp extends StatelessWidget {
6 | const CoffeeChallengeApp({Key? key}) : super(key: key);
7 |
8 | @override
9 | Widget build(BuildContext context) {
10 | return MaterialApp(
11 | title: 'Material App',
12 | debugShowCheckedModeBanner: false,
13 | theme: ThemeData(
14 | scaffoldBackgroundColor: Colors.white,
15 | primarySwatch: Colors.brown,
16 | primaryColor: Colors.white,
17 | textTheme: TextTheme(
18 | headline5: GoogleFonts.poppins(
19 | color: Colors.brown[700],
20 | fontWeight: FontWeight.w600,
21 | fontSize: 28,
22 | height: 1.1),
23 | headline2:
24 | GoogleFonts.poppins(fontWeight: FontWeight.w600, fontSize: 64),
25 | headline6: GoogleFonts.poppins(
26 | fontWeight: FontWeight.w500, fontSize: 22, height: 1.1),
27 | subtitle1: GoogleFonts.poppins(
28 | color: Colors.brown[400],
29 | fontWeight: FontWeight.w300,
30 | fontSize: 18,
31 | ),
32 | )),
33 | home: const CoffeeHomePage(),
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/model/coffee.dart:
--------------------------------------------------------------------------------
1 | class Coffee {
2 | final String name;
3 | final String pathImage;
4 | final double price;
5 |
6 | const Coffee(this.name, this.pathImage, this.price);
7 |
8 | static const coffeeList = [
9 | Coffee('Vietnamese Style Iced Coffee', 'assets/coffee_challenge/img/9.png', 4.2),
10 | Coffee('Classic Irish Coffee', 'assets/coffee_challenge/img/11.png', 4.3),
11 | Coffee('Americano', 'assets/coffee_challenge/img/8.png', 3.3),
12 | Coffee('Caramel Macchiato', 'assets/coffee_challenge/img/1.png', 3.2),
13 | Coffee('Toffee Nut Iced Latte', 'assets/coffee_challenge/img/7.png', 4.0),
14 | Coffee('Caramelized Pecan Latte', 'assets/coffee_challenge/img/4.png', 3.5),
15 | Coffee('Toffee Nut Latte', 'assets/coffee_challenge/img/5.png', 3.9),
16 | Coffee('Iced Coffe Mocha', 'assets/coffee_challenge/img/3.png', 3.2),
17 | Coffee('Capuchino', 'assets/coffee_challenge/img/6.png', 3.1),
18 | Coffee('Caramel Cold Drink', 'assets/coffee_challenge/img/2.png', 3.2),
19 | Coffee('Black Tea Latte', 'assets/coffee_challenge/img/10.png', 4.3),
20 | Coffee('Toffee Nut Crunch Latte', 'assets/coffee_challenge/img/12.png', 3.7),
21 | ];
22 | }
23 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/ui/coffee_home_page.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter_community_challenges/coffee_challenge/model/coffee.dart';
4 | import 'package:flutter_community_challenges/coffee_challenge/ui/coffee_list_page.dart';
5 | import 'package:flutter_community_challenges/coffee_challenge/ui/widgets/coffee_app_bar.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:google_fonts/google_fonts.dart';
8 |
9 | class CoffeeHomePage extends StatelessWidget {
10 | const CoffeeHomePage({Key? key}) : super(key: key);
11 |
12 | void _openCoffeeListPage(BuildContext context, SliderAction sliderAction) {
13 | Navigator.push(
14 | context,
15 | PageRouteBuilder(
16 | transitionDuration: const Duration(milliseconds: 400),
17 | pageBuilder: (context, animation, secondaryAnimation) {
18 | return FadeTransition(
19 | opacity: animation,
20 | child: CoffeeListPage(
21 | initialAction: sliderAction,
22 | ));
23 | },
24 | ),
25 | );
26 | }
27 |
28 | void _onVerticalDragUpdate(BuildContext context, DragUpdateDetails details) {
29 | if (details.primaryDelta! > 2.0) {
30 | _openCoffeeListPage(context, SliderAction.Previous);
31 | } else if (details.primaryDelta! < -2.0) {
32 | _openCoffeeListPage(context, SliderAction.Next);
33 | }
34 | }
35 |
36 | @override
37 | Widget build(BuildContext context) {
38 | final coffeeList = Coffee.coffeeList;
39 | return Scaffold(
40 | body: Stack(
41 | fit: StackFit.expand,
42 | children: [
43 | //--------------------------
44 | // Gradient Background
45 | //--------------------------
46 | const DecoratedBox(
47 | decoration: BoxDecoration(
48 | gradient: LinearGradient(
49 | begin: Alignment.topCenter,
50 | end: Alignment(0, -.3),
51 | colors: [Colors.brown, Colors.white],
52 | ),
53 | ),
54 | ),
55 | Column(
56 | children: [
57 | const CoffeeAppBar(brightness: Brightness.light),
58 | //----------------------
59 | // Coffee Images
60 | //----------------------
61 | Expanded(
62 | child: LayoutBuilder(
63 | builder: (context, constraints) {
64 | final height = constraints.maxHeight;
65 | return GestureDetector(
66 | onTap: () =>
67 | _openCoffeeListPage(context, SliderAction.None),
68 | onVerticalDragUpdate: (details) =>
69 | _onVerticalDragUpdate(context, details),
70 | child: Stack(
71 | children: [
72 | _CoffeeTransformedItem(
73 | displacement: 0,
74 | scale: .4,
75 | endTransitionOpacity: .5,
76 | coffee: coffeeList[0],
77 | ),
78 | _CoffeeTransformedItem(
79 | displacement: height * .1,
80 | scale: 1.1,
81 | endTransitionOpacity: .8,
82 | coffee: coffeeList[1],
83 | ),
84 | _CoffeeTransformedItem(
85 | displacement: height * .23,
86 | scale: 1.45,
87 | isOverflowed: true,
88 | fixedScale: 1.2,
89 | coffee: coffeeList[2],
90 | ),
91 | //----------------------------
92 | // App Coffee Title
93 | //----------------------------
94 | Align(
95 | alignment: Alignment(0, .4),
96 | child: Text.rich(
97 | TextSpan(
98 | text: 'Fika',
99 | children: [
100 | TextSpan(
101 | text: '\nCoffee',
102 | style: GoogleFonts.poppins(
103 | height: 1.0,
104 | fontSize: 60,
105 | ),
106 | )
107 | ],
108 | ),
109 | style: GoogleFonts.lilitaOne(
110 | fontSize: 70,
111 | color: Colors.white.withOpacity(.9),
112 | ),
113 | textAlign: TextAlign.center,
114 | ),
115 | ),
116 | _CoffeeTransformedItem(
117 | displacement: height * .75,
118 | scale: 1.75,
119 | fixedScale: 1.5,
120 | isOverflowed: true,
121 | coffee: coffeeList[3],
122 | ),
123 | ],
124 | ),
125 | );
126 | },
127 | ),
128 | )
129 | ],
130 | ),
131 | ],
132 | ),
133 | );
134 | }
135 | }
136 |
137 | class _CoffeeTransformedItem extends StatelessWidget {
138 | const _CoffeeTransformedItem({
139 | Key? key,
140 | required this.displacement,
141 | required this.coffee,
142 | this.fixedScale,
143 | this.endTransitionOpacity = 1.0,
144 | this.scale = 1.0,
145 | this.isOverflowed = false,
146 | }) : super(key: key);
147 |
148 | final double displacement;
149 | final double scale;
150 | final double? fixedScale;
151 | final bool isOverflowed;
152 | final double endTransitionOpacity;
153 | final Coffee coffee;
154 |
155 | @override
156 | Widget build(BuildContext context) {
157 | return Transform.translate(
158 | offset: Offset(0, displacement),
159 | child: Transform.scale(
160 | scale: scale,
161 | alignment: Alignment.topCenter,
162 | child: AspectRatio(
163 | aspectRatio: .85,
164 | child: Hero(
165 | tag: coffee.name,
166 | flightShuttleBuilder: (_, animation, __, ___, ____) {
167 | return AnimatedBuilder(
168 | animation: animation,
169 | builder: (_, child) {
170 | return Transform.scale(
171 | scale: (isOverflowed
172 | ? lerpDouble(fixedScale, 1.0, animation.value)!
173 | : 1.0),
174 | child: Opacity(
175 | opacity: lerpDouble(
176 | 1.0,
177 | endTransitionOpacity,
178 | animation.value,
179 | )!,
180 | child: child,
181 | ),
182 | );
183 | },
184 | child: Image.asset(coffee.pathImage),
185 | );
186 | },
187 | child: Image.asset(coffee.pathImage),
188 | ),
189 | ),
190 | ),
191 | );
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/ui/coffee_list_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_community_challenges/coffee_challenge/model/coffee.dart';
2 | import 'package:flutter_community_challenges/coffee_challenge/ui/coffee_order_page.dart';
3 | import 'package:flutter_community_challenges/coffee_challenge/ui/widgets/coffee_app_bar.dart';
4 | import 'package:flutter_community_challenges/coffee_challenge/ui/widgets/coffee_carousel.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | enum SliderAction {
8 | Next,
9 | Previous,
10 | None,
11 | }
12 |
13 | class CoffeeListPage extends StatefulWidget {
14 | const CoffeeListPage({
15 | Key? key,
16 | required this.initialAction,
17 | }) : super(key: key);
18 |
19 | final SliderAction initialAction;
20 |
21 | @override
22 | _CoffeeListPageState createState() => _CoffeeListPageState();
23 | }
24 |
25 | class _CoffeeListPageState extends State {
26 | late PageController _sliderPageController;
27 | late PageController _titlePageController;
28 | late int _index;
29 | late double _percent;
30 |
31 | @override
32 | void initState() {
33 | _index = 2;
34 | _sliderPageController = PageController(initialPage: _index);
35 | _titlePageController = PageController(initialPage: _index);
36 | _percent = 0.0;
37 | _sliderPageController.addListener(_pageListener);
38 |
39 | Future.delayed(const Duration(milliseconds: 400), () {
40 | _initialAction(widget.initialAction);
41 | });
42 |
43 | super.initState();
44 | }
45 |
46 | @override
47 | void dispose() {
48 | _sliderPageController.removeListener(_pageListener);
49 | _sliderPageController.dispose();
50 | _titlePageController.dispose();
51 | super.dispose();
52 | }
53 |
54 | void _pageListener() {
55 | _index = _sliderPageController.page!.floor();
56 | _percent = (_sliderPageController.page! - _index).abs();
57 | setState(() {});
58 | }
59 |
60 | void _openOrderPage(BuildContext context, Coffee coffee) {
61 | Navigator.push(
62 | context,
63 | PageRouteBuilder(
64 | pageBuilder: (context, animation, secondaryAnimation) {
65 | return FadeTransition(
66 | opacity: animation,
67 | child: CoffeeOrderPage(
68 | coffee: coffee,
69 | ),
70 | );
71 | },
72 | ),
73 | );
74 | }
75 |
76 | void _initialAction(SliderAction sliderAction) {
77 | switch (sliderAction) {
78 | case SliderAction.None:
79 | break;
80 | case SliderAction.Next:
81 | _sliderPageController.nextPage(
82 | duration: const Duration(milliseconds: 800),
83 | curve: Curves.fastOutSlowIn);
84 | break;
85 | case SliderAction.Previous:
86 | _sliderPageController.previousPage(
87 | duration: const Duration(milliseconds: 800),
88 | curve: Curves.fastOutSlowIn);
89 | break;
90 | }
91 | }
92 |
93 | void _onBackPage(BuildContext context) async {
94 | await _sliderPageController.animateToPage(2,
95 | duration: const Duration(milliseconds: 800),
96 | curve: Curves.fastOutSlowIn);
97 | Navigator.pop(context);
98 | }
99 |
100 | @override
101 | Widget build(BuildContext context) {
102 | final coffeeList = Coffee.coffeeList;
103 | return Scaffold(
104 | body: Column(
105 | children: [
106 | CoffeeAppBar(
107 | onTapBack: () => _onBackPage(context),
108 | ),
109 | //------------------------
110 | // Coffee names
111 | //------------------------
112 | SizedBox(
113 | height: MediaQuery.of(context).size.height * .17,
114 | child: PageView.builder(
115 | itemCount: coffeeList.length,
116 | physics: const NeverScrollableScrollPhysics(),
117 | controller: _titlePageController,
118 | itemBuilder: (context, index) {
119 | return _TitleCoffee(coffee: coffeeList[index]);
120 | },
121 | ),
122 | ),
123 | Expanded(
124 | child: Stack(
125 | children: [
126 | //------------------------------
127 | // Gradient background
128 | //------------------------------
129 | Positioned.fill(
130 | child: Container(
131 | decoration: BoxDecoration(
132 | gradient: LinearGradient(
133 | begin: Alignment.topCenter,
134 | end: Alignment.bottomCenter,
135 | stops: [0.75, 1.0],
136 | colors: [
137 | Colors.white,
138 | Color(0xFFbf7840),
139 | ],
140 | )),
141 | ),
142 | ),
143 | //--------------------------------
144 | // Animated Coffee Images
145 | //--------------------------------
146 | CoffeeCarousel(
147 | percent: _percent,
148 | coffeeList: coffeeList,
149 | index: _index,
150 | ),
151 | //--------------------------------
152 | // Void page view
153 | //--------------------------------
154 | PageView.builder(
155 | controller: _sliderPageController,
156 | onPageChanged: (value) {
157 | _titlePageController.animateToPage(value,
158 | duration: const Duration(milliseconds: 400),
159 | curve: Curves.fastOutSlowIn);
160 | },
161 | itemCount: coffeeList.length,
162 | physics: const BouncingScrollPhysics(),
163 | scrollDirection: Axis.vertical,
164 | itemBuilder: (context, index) {
165 | return InkWell(
166 | onTap: () => _openOrderPage(context, coffeeList[_index]),
167 | );
168 | },
169 | ),
170 | ],
171 | ),
172 | )
173 | ],
174 | ),
175 | );
176 | }
177 | }
178 |
179 | class _TitleCoffee extends StatelessWidget {
180 | const _TitleCoffee({
181 | Key? key,
182 | required this.coffee,
183 | }) : super(key: key);
184 |
185 | final Coffee coffee;
186 |
187 | @override
188 | Widget build(BuildContext context) {
189 | return Column(
190 | mainAxisAlignment: MainAxisAlignment.center,
191 | children: [
192 | SizedBox(
193 | width: MediaQuery.of(context).size.width * .65,
194 | child: Hero(
195 | tag: coffee.name + "title",
196 | child: Text(
197 | coffee.name,
198 | style: Theme.of(context).textTheme.headline5,
199 | maxLines: 2,
200 | textAlign: TextAlign.center,
201 | ),
202 | ),
203 | ),
204 | Text(
205 | "${coffee.price} €",
206 | style: Theme.of(context).textTheme.headline6!.copyWith(
207 | color: Colors.brown[400],
208 | ),
209 | ),
210 | ],
211 | );
212 | }
213 | }
214 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/ui/coffee_order_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_community_challenges/coffee_challenge/model/coffee.dart';
2 | import 'package:flutter_community_challenges/coffee_challenge/ui/widgets/coffee_app_bar.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_svg/flutter_svg.dart';
5 |
6 | enum CoffeeSize { Small, Medium, Big }
7 |
8 | class CoffeeOrderPage extends StatefulWidget {
9 | const CoffeeOrderPage({Key? key, required this.coffee}) : super(key: key);
10 | final Coffee coffee;
11 |
12 | @override
13 | _CoffeeOrderPageState createState() => _CoffeeOrderPageState();
14 | }
15 |
16 | class _CoffeeOrderPageState extends State {
17 | late CoffeeSize _selectedCoffeeSize;
18 | late PageController _pageController;
19 |
20 | @override
21 | void initState() {
22 | _selectedCoffeeSize = CoffeeSize.Medium;
23 | _pageController = PageController(initialPage: 1);
24 | super.initState();
25 | }
26 |
27 | void _changeCoffeeSize(CoffeeSize coffeeSize) {
28 | _pageController.animateToPage(
29 | coffeeSize.index,
30 | duration: const Duration(milliseconds: 300),
31 | curve: Curves.fastOutSlowIn,
32 | );
33 | setState(() {
34 | _selectedCoffeeSize = coffeeSize;
35 | });
36 | }
37 |
38 | double _getSizePricePercent(CoffeeSize coffeeSize) {
39 | switch (coffeeSize) {
40 | case CoffeeSize.Small:
41 | return 0.8;
42 | case CoffeeSize.Medium:
43 | return 1.0;
44 | case CoffeeSize.Big:
45 | return 1.2;
46 | default:
47 | return 1.0;
48 | }
49 | }
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | final size = MediaQuery.of(context).size;
54 | return Scaffold(
55 | body: Column(
56 | children: [
57 | const CoffeeAppBar(),
58 | //------------------------
59 | // Coffee name
60 | //------------------------
61 | SizedBox(
62 | width: size.width * .65,
63 | child: Hero(
64 | tag: widget.coffee.name + "title",
65 | child: Text(
66 | widget.coffee.name,
67 | style: Theme.of(context).textTheme.headline5,
68 | maxLines: 2,
69 | textAlign: TextAlign.center,
70 | ),
71 | ),
72 | ),
73 | //------------------------
74 | // Coffee Image
75 | //------------------------
76 | Expanded(
77 | flex: 4,
78 | child: Stack(
79 | fit: StackFit.expand,
80 | children: [
81 | Positioned.fill(
82 | child: Hero(
83 | tag: widget.coffee.name,
84 | child: PageView(
85 | controller: _pageController,
86 | physics: const NeverScrollableScrollPhysics(),
87 | children: [
88 | Padding(
89 | padding: const EdgeInsets.only(top: 80),
90 | child: Image.asset(widget.coffee.pathImage),
91 | ),
92 | Padding(
93 | padding: const EdgeInsets.only(top: 40),
94 | child: Image.asset(widget.coffee.pathImage),
95 | ),
96 | Image.asset(widget.coffee.pathImage),
97 | ],
98 | ),
99 | ),
100 | ),
101 | Align(
102 | alignment: Alignment(-.7, .8),
103 | //-----------------------------
104 | // Text price animated
105 | //-----------------------------
106 | child: TweenAnimationBuilder(
107 | duration: const Duration(milliseconds: 600),
108 | tween: Tween(begin: 1.0, end: 0.0),
109 | curve: Curves.fastOutSlowIn,
110 | builder: (context, value, child) {
111 | return Transform.translate(
112 | offset: Offset(-(size.width * .5) * value,
113 | (size.height * .4) * value),
114 | child: child,
115 | );
116 | },
117 | //------------------------------
118 | // Change Price Animation
119 | //------------------------------
120 | child: TweenAnimationBuilder(
121 | duration: const Duration(milliseconds: 600),
122 | tween: Tween(
123 | begin: 0.0,
124 | end: _getSizePricePercent(_selectedCoffeeSize),
125 | ),
126 | curve: Curves.fastOutSlowIn,
127 | builder: (context, value, _) {
128 | return Transform.scale(
129 | scale: value,
130 | child: Text(
131 | "${(widget.coffee.price * value).toStringAsFixed(1)}\$",
132 | style: Theme.of(context)
133 | .textTheme
134 | .headline2!
135 | .copyWith(
136 | color: Colors.white,
137 | shadows: [
138 | Shadow(
139 | color: Colors.black54,
140 | blurRadius: 30,
141 | )
142 | ],
143 | ),
144 | ),
145 | );
146 | }),
147 | ),
148 | ),
149 | Align(
150 | alignment: Alignment(.7, -.7),
151 | //-----------------------------
152 | // Add Button Animated
153 | //-----------------------------
154 | child: TweenAnimationBuilder(
155 | duration: const Duration(milliseconds: 600),
156 | tween: Tween(begin: 1.0, end: 0.0),
157 | curve: Curves.fastOutSlowIn,
158 | builder: (context, value, child) {
159 | return Transform.translate(
160 | offset: Offset((size.width * .3) * value, 0),
161 | child: Transform.rotate(
162 | angle: 4.28 * value,
163 | child: child,
164 | ),
165 | );
166 | },
167 | child: FloatingActionButton(
168 | onPressed: () {},
169 | mini: true,
170 | elevation: 10,
171 | backgroundColor: Colors.white,
172 | foregroundColor: Colors.brown[700],
173 | child: Icon(Icons.add),
174 | ),
175 | ),
176 | )
177 | ],
178 | ),
179 | ),
180 | //------------------------
181 | // Coffee Sizes
182 | //------------------------
183 | Expanded(
184 | child: TweenAnimationBuilder(
185 | duration: const Duration(milliseconds: 600),
186 | tween: Tween(begin: 1.0, end: 0.0),
187 | curve: Curves.fastOutSlowIn,
188 | builder: (context, value, child) {
189 | return Transform.translate(
190 | offset: Offset(0, (size.height * .2) * value),
191 | child: child,
192 | );
193 | },
194 | child: Row(
195 | mainAxisAlignment: MainAxisAlignment.center,
196 | children: List.generate(CoffeeSize.values.length, (index) {
197 | final coffeeSize = CoffeeSize.values[index];
198 | //----------------------------
199 | // Coffee Size Option
200 | //----------------------------
201 | return Padding(
202 | padding: const EdgeInsets.symmetric(horizontal: 15.0),
203 | child: _CoffeeSizeOption(
204 | isSelected: (coffeeSize == _selectedCoffeeSize),
205 | coffeeSize: coffeeSize,
206 | onTap: () => _changeCoffeeSize(coffeeSize)),
207 | );
208 | }),
209 | ),
210 | ),
211 | ),
212 | //------------------------
213 | // Coffee temperatures
214 | //------------------------
215 | Expanded(
216 | child: TweenAnimationBuilder(
217 | duration: const Duration(milliseconds: 600),
218 | tween: Tween(begin: 1.0, end: 0.0),
219 | curve: Curves.fastOutSlowIn,
220 | builder: (context, value, child) {
221 | return Transform.translate(
222 | offset: Offset(0, (size.height * .2) * value),
223 | child: child,
224 | );
225 | },
226 | child: const _CoffeeTemperatures(),
227 | ),
228 | ),
229 | ],
230 | ),
231 | );
232 | }
233 | }
234 |
235 | class _CoffeeTemperatures extends StatelessWidget {
236 | const _CoffeeTemperatures({
237 | Key? key,
238 | }) : super(key: key);
239 |
240 | @override
241 | Widget build(BuildContext context) {
242 | return Row(
243 | children: [
244 | Expanded(
245 | child: Container(
246 | alignment: Alignment.center,
247 | decoration: BoxDecoration(color: Colors.white, boxShadow: [
248 | BoxShadow(
249 | color: Colors.black12, blurRadius: 10, offset: Offset(3, 10))
250 | ]),
251 | child: Text(
252 | 'Hot | Warm',
253 | style: Theme.of(context)
254 | .textTheme
255 | .subtitle1!
256 | .copyWith(color: Colors.brown[700]),
257 | ),
258 | ),
259 | ),
260 | Expanded(
261 | child: Container(
262 | alignment: Alignment.center,
263 | child: Text(
264 | 'Cold | Ice',
265 | style: Theme.of(context)
266 | .textTheme
267 | .subtitle1!
268 | .copyWith(color: Colors.grey[400]),
269 | ),
270 | ),
271 | ),
272 | ],
273 | );
274 | }
275 | }
276 |
277 | class _CoffeeSizeOption extends StatelessWidget {
278 | const _CoffeeSizeOption({
279 | Key? key,
280 | required this.isSelected,
281 | required this.coffeeSize,
282 | required this.onTap,
283 | }) : super(key: key);
284 |
285 | final bool isSelected;
286 | final CoffeeSize coffeeSize;
287 | final VoidCallback onTap;
288 |
289 | @override
290 | Widget build(BuildContext context) {
291 | final labelSize = coffeeSize.toString().split('.')[1][0].toLowerCase();
292 | return InkWell(
293 | onTap: onTap,
294 | splashColor: Colors.transparent,
295 | highlightColor: Colors.transparent,
296 | child: ShaderMask(
297 | shaderCallback: (bounds) => LinearGradient(
298 | begin: Alignment.topCenter,
299 | end: Alignment.bottomCenter,
300 | colors: isSelected
301 | ? [Colors.brown, Colors.orange]
302 | : [Colors.grey[300]!, Colors.grey[300]!],
303 | ).createShader(bounds),
304 | child: Column(
305 | mainAxisAlignment: MainAxisAlignment.center,
306 | children: [
307 | SvgPicture.asset(
308 | "assets/coffee_challenge/svg/$labelSize-coffee-cup.svg",
309 | width: 45.0,
310 | color: Colors.white,
311 | ),
312 | Text(
313 | labelSize.toUpperCase(),
314 | style: Theme.of(context).textTheme.headline6!.copyWith(
315 | color: Colors.white,
316 | ),
317 | )
318 | ],
319 | ),
320 | ),
321 | );
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/ui/widgets/coffee_app_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CoffeeAppBar extends StatelessWidget {
4 | const CoffeeAppBar({
5 | Key? key,
6 | this.brightness = Brightness.dark,
7 | this.onTapBack,
8 | }) : super(key: key);
9 | final Brightness brightness;
10 | final VoidCallback? onTapBack;
11 |
12 | @override
13 | Widget build(BuildContext context) {
14 | final _isDarkBrightness = (brightness == Brightness.dark);
15 | return SafeArea(
16 | child: Padding(
17 | padding: const EdgeInsets.all(12.0),
18 | child: Row(
19 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
20 | children: [
21 | IconButton(
22 | color: _isDarkBrightness ? Colors.black : Colors.white,
23 | icon: Icon(Icons.arrow_back_ios),
24 | onPressed: onTapBack ??
25 | () {
26 | if (Navigator.canPop(context)) Navigator.pop(context);
27 | },
28 | ),
29 | Stack(
30 | children: [
31 | IconButton(
32 | iconSize: 32,
33 | color: _isDarkBrightness ? Colors.black : Colors.white,
34 | icon: Icon(Icons.shopping_bag_outlined),
35 | onPressed: () {},
36 | ),
37 | Positioned(
38 | bottom: 8,
39 | right: 8,
40 | child: Container(
41 | height: 14,
42 | width: 14,
43 | decoration: BoxDecoration(
44 | color: _isDarkBrightness ? Colors.orange : Colors.white,
45 | shape: BoxShape.circle,
46 | ),
47 | child: FittedBox(
48 | child: Text(
49 | '1',
50 | style: Theme.of(context).textTheme.caption!.copyWith(
51 | color: _isDarkBrightness
52 | ? Colors.white
53 | : Colors.brown[700],
54 | fontWeight: FontWeight.bold,
55 | ),
56 | ),
57 | ),
58 | ),
59 | )
60 | ],
61 | ),
62 | ],
63 | ),
64 | ),
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/coffee_challenge/ui/widgets/coffee_carousel.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:flutter_community_challenges/coffee_challenge/model/coffee.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 |
7 | class CoffeeCarousel extends StatelessWidget {
8 | const CoffeeCarousel({
9 | Key? key,
10 | required double percent,
11 | required this.coffeeList,
12 | required int index,
13 | }) : _percent = percent,
14 | _index = index,
15 | super(key: key);
16 |
17 | final double _percent;
18 | final List coffeeList;
19 | final int _index;
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return LayoutBuilder(
24 | builder: (context, constraints) {
25 | final height = constraints.maxHeight;
26 | return Stack(
27 | alignment: Alignment.center,
28 | children: [
29 | // Third coffee
30 | if (_index > 1)
31 | _CoffeeTransforms(
32 | coffee: coffeeList[_index - 2],
33 | scale: lerpDouble(.3, 0, _percent)!,
34 | opacity: lerpDouble(0.5, 0.0, _percent)!,
35 | ),
36 |
37 | // Second coffee
38 | if (_index > 0)
39 | _CoffeeTransforms(
40 | coffee: coffeeList[_index - 1],
41 | displacement: lerpDouble((height * .1), 0, _percent)!,
42 | scale: lerpDouble(.6, .3, _percent)!,
43 | opacity: lerpDouble(0.8, 0.5, _percent)!,
44 | ),
45 |
46 | // First coffee
47 | _CoffeeTransforms(
48 | coffee: coffeeList[_index],
49 | displacement: lerpDouble((height * .25), (height * .1), _percent)!,
50 | scale: lerpDouble(1.0, .6, _percent)!,
51 | opacity: lerpDouble(1.0, 0.8, _percent)!,
52 | ),
53 |
54 | // Hide bottom coffee
55 | if (_index < coffeeList.length - 1)
56 | _CoffeeTransforms(
57 | coffee: coffeeList[_index + 1],
58 | displacement: lerpDouble(height, (height * .25), _percent)!,
59 | scale: lerpDouble(2.0, 1.0, _percent)!,
60 | ),
61 | ],
62 | );
63 | },
64 | );
65 | }
66 | }
67 |
68 | class _CoffeeTransforms extends StatelessWidget {
69 | const _CoffeeTransforms(
70 | {Key? key,
71 | required this.coffee,
72 | this.displacement = 0.0,
73 | this.scale = 1.0,
74 | this.opacity = 1.0})
75 | : super(key: key);
76 |
77 | final double displacement;
78 | final double scale;
79 | final double opacity;
80 | final Coffee coffee;
81 |
82 | @override
83 | Widget build(BuildContext context) {
84 | return Transform.translate(
85 | offset: Offset(0, displacement),
86 | child: Transform.scale(
87 | alignment: Alignment.topCenter,
88 | scale: scale,
89 | child: Opacity(
90 | opacity: opacity,
91 | child: _CoffeeImage(
92 | coffee: coffee,
93 | ),
94 | ),
95 | ),
96 | );
97 | }
98 | }
99 | class _CoffeeImage extends StatelessWidget {
100 | const _CoffeeImage({
101 | Key? key,
102 | required this.coffee,
103 | }) : super(key: key);
104 | final Coffee coffee;
105 |
106 | @override
107 | Widget build(BuildContext context) {
108 | return Align(
109 | alignment: Alignment.topCenter,
110 | child: AspectRatio(
111 | aspectRatio: 0.85,
112 | child: Hero(
113 | tag: coffee.name,
114 | child: Image.asset(
115 | coffee.pathImage,
116 | ),
117 | ),
118 | ),
119 | );
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:flutter_community_challenges/boats_challenge/main.dart';
4 | import 'package:flutter_community_challenges/coffee_challenge/coffee_app.dart';
5 |
6 | import 'bank_challenge/bank_challenge_app.dart';
7 |
8 | void main() {
9 | SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
10 | statusBarColor: Colors.transparent,
11 | statusBarIconBrightness: Brightness.light,
12 | ));
13 | runApp(MyApp());
14 | }
15 |
16 | class MyApp extends StatelessWidget {
17 | @override
18 | Widget build(BuildContext context) {
19 | return MaterialApp(
20 | title: 'Hispanic Community Challenges',
21 | debugShowCheckedModeBanner: false,
22 | theme: ThemeData(
23 | primarySwatch: Colors.blue,
24 | ),
25 | home: ChallengePage(),
26 | );
27 | }
28 | }
29 |
30 | class ChallengePage extends StatelessWidget {
31 | const ChallengePage({Key? key}) : super(key: key);
32 |
33 | void _openApp(BuildContext context, Widget app) {
34 | final route = MaterialPageRoute(builder: (context) => app);
35 | Navigator.push(context, route);
36 | }
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | final apps = const [
41 | CoffeeChallengeApp(),
42 | BoatsChallengeApp(),
43 | BankChallengeApp(),
44 | ];
45 | final appsTitle = const [
46 | 'Coffee Challenge',
47 | 'Boats Challenge',
48 | 'Bank Challenge',
49 | ];
50 | return Scaffold(
51 | appBar: AppBar(
52 | title: Text('Flutter Community Challenges'),
53 | ),
54 | body: Center(
55 | child: ListView.builder(
56 | itemCount: apps.length,
57 | padding: const EdgeInsets.all(20.0),
58 | itemBuilder: (context, index) {
59 | return Padding(
60 | padding: const EdgeInsets.all(8.0),
61 | child: TextButton(
62 | onPressed: () => _openApp(context, apps[index]),
63 | style: TextButton.styleFrom(
64 | backgroundColor: Colors.blueAccent,
65 | ),
66 | child: Text(
67 | appsTitle[index],
68 | style: TextStyle(color: Colors.white),
69 | ),
70 | ),
71 | );
72 | },
73 | ),
74 | ),
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/pubspec.lock:
--------------------------------------------------------------------------------
1 | # Generated by pub
2 | # See https://dart.dev/tools/pub/glossary#lockfile
3 | packages:
4 | async:
5 | dependency: transitive
6 | description:
7 | name: async
8 | url: "https://pub.dartlang.org"
9 | source: hosted
10 | version: "2.6.1"
11 | boolean_selector:
12 | dependency: transitive
13 | description:
14 | name: boolean_selector
15 | url: "https://pub.dartlang.org"
16 | source: hosted
17 | version: "2.1.0"
18 | characters:
19 | dependency: transitive
20 | description:
21 | name: characters
22 | url: "https://pub.dartlang.org"
23 | source: hosted
24 | version: "1.1.0"
25 | charcode:
26 | dependency: transitive
27 | description:
28 | name: charcode
29 | url: "https://pub.dartlang.org"
30 | source: hosted
31 | version: "1.2.0"
32 | clock:
33 | dependency: transitive
34 | description:
35 | name: clock
36 | url: "https://pub.dartlang.org"
37 | source: hosted
38 | version: "1.1.0"
39 | collection:
40 | dependency: transitive
41 | description:
42 | name: collection
43 | url: "https://pub.dartlang.org"
44 | source: hosted
45 | version: "1.15.0"
46 | crypto:
47 | dependency: transitive
48 | description:
49 | name: crypto
50 | url: "https://pub.dartlang.org"
51 | source: hosted
52 | version: "3.0.1"
53 | cupertino_icons:
54 | dependency: "direct main"
55 | description:
56 | name: cupertino_icons
57 | url: "https://pub.dartlang.org"
58 | source: hosted
59 | version: "1.0.3"
60 | fake_async:
61 | dependency: transitive
62 | description:
63 | name: fake_async
64 | url: "https://pub.dartlang.org"
65 | source: hosted
66 | version: "1.2.0"
67 | ffi:
68 | dependency: transitive
69 | description:
70 | name: ffi
71 | url: "https://pub.dartlang.org"
72 | source: hosted
73 | version: "1.1.2"
74 | file:
75 | dependency: transitive
76 | description:
77 | name: file
78 | url: "https://pub.dartlang.org"
79 | source: hosted
80 | version: "6.1.2"
81 | flutter:
82 | dependency: "direct main"
83 | description: flutter
84 | source: sdk
85 | version: "0.0.0"
86 | flutter_svg:
87 | dependency: "direct main"
88 | description:
89 | name: flutter_svg
90 | url: "https://pub.dartlang.org"
91 | source: hosted
92 | version: "0.22.0"
93 | flutter_test:
94 | dependency: "direct dev"
95 | description: flutter
96 | source: sdk
97 | version: "0.0.0"
98 | google_fonts:
99 | dependency: "direct main"
100 | description:
101 | name: google_fonts
102 | url: "https://pub.dartlang.org"
103 | source: hosted
104 | version: "2.1.0"
105 | http:
106 | dependency: transitive
107 | description:
108 | name: http
109 | url: "https://pub.dartlang.org"
110 | source: hosted
111 | version: "0.13.3"
112 | http_parser:
113 | dependency: transitive
114 | description:
115 | name: http_parser
116 | url: "https://pub.dartlang.org"
117 | source: hosted
118 | version: "4.0.0"
119 | matcher:
120 | dependency: transitive
121 | description:
122 | name: matcher
123 | url: "https://pub.dartlang.org"
124 | source: hosted
125 | version: "0.12.10"
126 | meta:
127 | dependency: transitive
128 | description:
129 | name: meta
130 | url: "https://pub.dartlang.org"
131 | source: hosted
132 | version: "1.3.0"
133 | path:
134 | dependency: transitive
135 | description:
136 | name: path
137 | url: "https://pub.dartlang.org"
138 | source: hosted
139 | version: "1.8.0"
140 | path_drawing:
141 | dependency: transitive
142 | description:
143 | name: path_drawing
144 | url: "https://pub.dartlang.org"
145 | source: hosted
146 | version: "0.5.1"
147 | path_parsing:
148 | dependency: transitive
149 | description:
150 | name: path_parsing
151 | url: "https://pub.dartlang.org"
152 | source: hosted
153 | version: "0.2.1"
154 | path_provider:
155 | dependency: transitive
156 | description:
157 | name: path_provider
158 | url: "https://pub.dartlang.org"
159 | source: hosted
160 | version: "2.0.2"
161 | path_provider_linux:
162 | dependency: transitive
163 | description:
164 | name: path_provider_linux
165 | url: "https://pub.dartlang.org"
166 | source: hosted
167 | version: "2.0.0"
168 | path_provider_macos:
169 | dependency: transitive
170 | description:
171 | name: path_provider_macos
172 | url: "https://pub.dartlang.org"
173 | source: hosted
174 | version: "2.0.0"
175 | path_provider_platform_interface:
176 | dependency: transitive
177 | description:
178 | name: path_provider_platform_interface
179 | url: "https://pub.dartlang.org"
180 | source: hosted
181 | version: "2.0.1"
182 | path_provider_windows:
183 | dependency: transitive
184 | description:
185 | name: path_provider_windows
186 | url: "https://pub.dartlang.org"
187 | source: hosted
188 | version: "2.0.1"
189 | pedantic:
190 | dependency: transitive
191 | description:
192 | name: pedantic
193 | url: "https://pub.dartlang.org"
194 | source: hosted
195 | version: "1.11.1"
196 | petitparser:
197 | dependency: transitive
198 | description:
199 | name: petitparser
200 | url: "https://pub.dartlang.org"
201 | source: hosted
202 | version: "4.1.0"
203 | platform:
204 | dependency: transitive
205 | description:
206 | name: platform
207 | url: "https://pub.dartlang.org"
208 | source: hosted
209 | version: "3.0.0"
210 | plugin_platform_interface:
211 | dependency: transitive
212 | description:
213 | name: plugin_platform_interface
214 | url: "https://pub.dartlang.org"
215 | source: hosted
216 | version: "2.0.1"
217 | process:
218 | dependency: transitive
219 | description:
220 | name: process
221 | url: "https://pub.dartlang.org"
222 | source: hosted
223 | version: "4.2.1"
224 | sky_engine:
225 | dependency: transitive
226 | description: flutter
227 | source: sdk
228 | version: "0.0.99"
229 | source_span:
230 | dependency: transitive
231 | description:
232 | name: source_span
233 | url: "https://pub.dartlang.org"
234 | source: hosted
235 | version: "1.8.1"
236 | stack_trace:
237 | dependency: transitive
238 | description:
239 | name: stack_trace
240 | url: "https://pub.dartlang.org"
241 | source: hosted
242 | version: "1.10.0"
243 | stream_channel:
244 | dependency: transitive
245 | description:
246 | name: stream_channel
247 | url: "https://pub.dartlang.org"
248 | source: hosted
249 | version: "2.1.0"
250 | string_scanner:
251 | dependency: transitive
252 | description:
253 | name: string_scanner
254 | url: "https://pub.dartlang.org"
255 | source: hosted
256 | version: "1.1.0"
257 | term_glyph:
258 | dependency: transitive
259 | description:
260 | name: term_glyph
261 | url: "https://pub.dartlang.org"
262 | source: hosted
263 | version: "1.2.0"
264 | test_api:
265 | dependency: transitive
266 | description:
267 | name: test_api
268 | url: "https://pub.dartlang.org"
269 | source: hosted
270 | version: "0.3.0"
271 | typed_data:
272 | dependency: transitive
273 | description:
274 | name: typed_data
275 | url: "https://pub.dartlang.org"
276 | source: hosted
277 | version: "1.3.0"
278 | vector_math:
279 | dependency: transitive
280 | description:
281 | name: vector_math
282 | url: "https://pub.dartlang.org"
283 | source: hosted
284 | version: "2.1.0"
285 | win32:
286 | dependency: transitive
287 | description:
288 | name: win32
289 | url: "https://pub.dartlang.org"
290 | source: hosted
291 | version: "2.2.5"
292 | xdg_directories:
293 | dependency: transitive
294 | description:
295 | name: xdg_directories
296 | url: "https://pub.dartlang.org"
297 | source: hosted
298 | version: "0.2.0"
299 | xml:
300 | dependency: transitive
301 | description:
302 | name: xml
303 | url: "https://pub.dartlang.org"
304 | source: hosted
305 | version: "5.1.2"
306 | sdks:
307 | dart: ">=2.13.0 <3.0.0"
308 | flutter: ">=1.24.0-7.0"
309 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: flutter_community_challenges
2 | description: Hispanic Community Fluter Challenges
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.12.0 <3.0.0"
22 |
23 |
24 | dependencies:
25 | flutter:
26 | sdk: flutter
27 | google_fonts: ^2.1.0
28 | flutter_svg: ^0.22.0
29 |
30 | # The following adds the Cupertino Icons font to your application.
31 | # Use with the CupertinoIcons class for iOS style icons.
32 | cupertino_icons: ^1.0.2
33 |
34 | dev_dependencies:
35 | flutter_test:
36 | sdk: flutter
37 |
38 | # For information on the generic Dart part of this file, see the
39 | # following page: https://dart.dev/tools/pub/pubspec
40 |
41 | # The following section is specific to Flutter.
42 | flutter:
43 |
44 | # The following line ensures that the Material Icons font is
45 | # included with your application, so that you can use the icons in
46 | # the material Icons class.
47 | uses-material-design: true
48 |
49 | # To add assets to your application, add an assets section, like this:
50 | assets:
51 | - assets/coffee_challenge/img/
52 | - assets/coffee_challenge/svg/
53 | - assets/boats_challenge/img/
54 | - assets/bank_challenge/img/
55 | # - images/a_dot_ham.jpeg
56 |
57 | # An image asset can refer to one or more resolution-specific "variants", see
58 | # https://flutter.dev/assets-and-images/#resolution-aware.
59 |
60 | # For details regarding adding assets from package dependencies, see
61 | # https://flutter.dev/assets-and-images/#from-packages
62 |
63 | # To add custom fonts to your application, add a fonts section here,
64 | # in this "flutter" section. Each entry in this list should have a
65 | # "family" key with the font family name, and a "fonts" key with a
66 | # list giving the asset and other descriptors for the font. For
67 | # example:
68 | # fonts:
69 | # - family: Schyler
70 | # fonts:
71 | # - asset: fonts/Schyler-Regular.ttf
72 | # - asset: fonts/Schyler-Italic.ttf
73 | # style: italic
74 | # - family: Trajan Pro
75 | # fonts:
76 | # - asset: fonts/TrajanPro.ttf
77 | # - asset: fonts/TrajanPro_Bold.ttf
78 | # weight: 700
79 | #
80 | # For details regarding fonts from package dependencies,
81 | # see https://flutter.dev/custom-fonts/#from-packages
82 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:flutter_community_challenges/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------