├── .github └── FUNDING.yml ├── .gitignore ├── .metadata ├── LICENSE ├── README.md ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── pedromassango │ │ │ │ └── my_flutter_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 ├── images └── martian_surface.png ├── 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.h │ ├── AppDelegate.m │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── 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 │ └── main.m ├── lib ├── banking_app.dart ├── bottom_menu_bar.dart ├── bottom_nav_bar.dart ├── bsd_login_register_challenge.dart ├── bubbles_rain.dart ├── coffee_app_auth.dart ├── crazy_switch_challenge.dart ├── flutter_experiment.dart ├── flying_widget.dart ├── foldable_options_menu.dart ├── grid_list_example.dart ├── indexed_list.dart ├── liquid_swipe_challenge.dart ├── login_challenge.dart ├── login_profile_challenge.dart ├── main.dart ├── minimal_login.dart ├── mobile_dashboard.dart ├── number_picker.dart ├── profile_challenge.dart ├── profile_design.dart ├── search_app_bar.dart ├── sliding_login.dart ├── sushi_order.dart ├── ticket_booking.dart ├── titled_bottom_bar.dart ├── transformation_example.dart └── world_clock.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── app_icon_1024.png │ │ ├── app_icon_128.png │ │ ├── app_icon_16.png │ │ ├── app_icon_256.png │ │ ├── app_icon_32.png │ │ ├── app_icon_512.png │ │ └── app_icon_64.png │ ├── Base.lproj │ └── MainMenu.xib │ ├── Configs │ ├── AppInfo.xcconfig │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements ├── pubspec.yaml ├── screenshots ├── bank_app_ui.gif ├── coffee_app_auth_page.gif ├── dashboard.png ├── delivery.gif ├── delivery.png ├── home.png ├── login.png ├── navy2.gif ├── options_menu.gif ├── profile.png ├── profile_design.png ├── sliding_login.png ├── slidl.gif ├── sushi_ui.gif ├── ticket_booking.gif ├── titled_bottom_bar.gif └── world_clock.png └── test └── widget_test.dart /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: pedromassango 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.lock 4 | *.log 5 | *.pyc 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # Visual Studio Code related 20 | .vscode/ 21 | 22 | # Flutter/Dart/Pub related 23 | **/doc/api/ 24 | .dart_tool/ 25 | .flutter-plugins 26 | .packages 27 | .pub-cache/ 28 | .pub/ 29 | build/ 30 | 31 | # Android related 32 | **/android/**/gradle-wrapper.jar 33 | **/android/.gradle 34 | **/android/captures/ 35 | **/android/gradlew 36 | **/android/gradlew.bat 37 | **/android/local.properties 38 | **/android/**/GeneratedPluginRegistrant.java 39 | 40 | # iOS/XCode related 41 | **/ios/**/*.mode1v3 42 | **/ios/**/*.mode2v3 43 | **/ios/**/*.moved-aside 44 | **/ios/**/*.pbxuser 45 | **/ios/**/*.perspectivev3 46 | **/ios/**/*sync/ 47 | **/ios/**/.sconsign.dblite 48 | **/ios/**/.tags* 49 | **/ios/**/.vagrant/ 50 | **/ios/**/DerivedData/ 51 | **/ios/**/Icon? 52 | **/ios/**/Pods/ 53 | **/ios/**/.symlinks/ 54 | **/ios/**/profile 55 | **/ios/**/xcuserdata 56 | **/ios/.generated/ 57 | **/ios/Flutter/App.framework 58 | **/ios/Flutter/Flutter.framework 59 | **/ios/Flutter/Generated.xcconfig 60 | **/ios/Flutter/app.flx 61 | **/ios/Flutter/app.zip 62 | **/ios/Flutter/flutter_assets/ 63 | **/ios/ServiceDefinitions.json 64 | **/ios/Runner/GeneratedPluginRegistrant.* 65 | 66 | # Exceptions to above rules. 67 | !**/ios/**/default.mode1v3 68 | !**/ios/**/default.mode2v3 69 | !**/ios/**/default.pbxuser 70 | !**/ios/**/default.perspectivev3 71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 72 | 73 | /lib/flutter_create.dart 74 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: beta 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 Pedro Massango 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # My Flutter Challenges 2 | 3 | A new Flutter project containing all my flutter UI challenges. 4 | 5 | ### How to get the code? 6 | 7 | You just click on the title of each challenge, and it will show you the complete code. 8 | Each challenge is self-contained in a single `.dart` file, so you can just copy/paste and run it. 9 | 10 | YouTube playlists about Flutter: https://www.youtube.com/playlist?list=PLum90SMJW-vltQ_ERf3rhjq_UZWJ2enEG 11 | 12 | #### :heart: Star :heart: the repo to support the project or [Follow Me](https://github.com/pedromassango).Thanks! 13 | [![Twitter Follow](https://img.shields.io/twitter/follow/pedromassangom.svg?style=social&label=Follow)](https://twitter.com/pedromassangom) 14 | 15 | ### Warning 16 | All the code in this repository are mean for demo only and are not optmized. 17 | Make sure do improve the code before using it. 18 | 19 | ## Screenshots 20 | 21 | | [Bank App UI](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/banking_app.dart) | [Sushi app UI/UX](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/sushi_order.dart) | [Ticket Booking](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/ticket_booking.dart) | 22 | | ------------- | ------------- | ------------- | 23 | | | | | 24 | 25 | | [Sliding Login & Register](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/sliding_login.dart) | [Bottom Navy Bar](https://github.com/pedromassango/bottom_navy_bar) | [Custom Drawer](https://github.com/pedromassango/flutter_delivery) | 26 | | ------------- | ------------- | ------------- | 27 | | | | | 28 | 29 | 30 | 31 | | [Titled Bottom Navigation Bar](https://github.com/pedromassango/titled_navigation_bar) | [Mobile Dashboard](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/mobile_dashboard.dart) | [Foldable Options Menu](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/foldable_options_menu.dart) | 32 | | ------------- | ------------- | ------------- | 33 | | | | | 34 | 35 | | [Login](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/login_challenge.dart) | [Profile](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/profile_challenge.dart) | [Home screen](https://github.com/pedromassango/flutter_famguard) | 36 | | ----- | ------- | ------------- | 37 | | | | | 38 | 39 | | [Number Picker](https://github.com/pedromassango/slider_number_picker) | [Profile Design](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/profile_design.dart) | [World Clock](https://github.com/pedromassango/my_flutter_challenges/blob/master/lib/world_clock.dart) | 40 | | ------------- | ----- | ----- | 41 | | | | | 42 | 43 | | [Coffee App - Auth Page](/screenshots/coffee_app_auth_page.gif) 44 | | ------------- | 45 | | | 46 | 47 | ## Getting Started 48 | 49 | This project is a starting point for a Flutter application. 50 | 51 | A few resources to get you started if this is your first Flutter project: 52 | 53 | - [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab) 54 | - [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook) 55 | 56 | For help getting started with Flutter, view our 57 | [online documentation](https://flutter.io/docs), which offers tutorials, 58 | samples, guidance on mobile development, and a full API reference. 59 | -------------------------------------------------------------------------------- /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.pedromassango.my_flutter_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/pedromassango/my_flutter_challenges/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.pedromassango.my_flutter_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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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 | -------------------------------------------------------------------------------- /images/martian_surface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/images/martian_surface.png -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 40 | 41 | 42 | 43 | 44 | 45 | 56 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 75 | 77 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 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.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : FlutterAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "GeneratedPluginRegistrant.h" 3 | 4 | @implementation AppDelegate 5 | 6 | - (BOOL)application:(UIApplication *)application 7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 8 | [GeneratedPluginRegistrant registerWithRegistry:self]; 9 | // Override point for customization after application launch. 10 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 11 | } 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/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/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_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 | -------------------------------------------------------------------------------- /ios/Runner/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char* argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/bottom_menu_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: "Bottom Menu Bar", 10 | home: HomePage(), 11 | ); 12 | } 13 | } 14 | 15 | class HomePage extends StatefulWidget { 16 | @override 17 | _HomePageState createState() => _HomePageState(); 18 | } 19 | 20 | class _HomePageState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return Scaffold( 24 | backgroundColor: Colors.white, 25 | appBar: AppBar( 26 | elevation: 2, 27 | title: Text("Bottom Menu Bar"), 28 | ), 29 | bottomNavigationBar: BottomMenuBar(), 30 | ); 31 | } 32 | } 33 | 34 | class BottomMenuBar extends StatefulWidget { 35 | @override 36 | _BottomMenuBarState createState() => _BottomMenuBarState(); 37 | } 38 | 39 | class _BottomMenuBarState 40 | extends State 41 | with SingleTickerProviderStateMixin{ 42 | 43 | bool animate = false; 44 | Animation sizeAnim; 45 | AnimationController controller; 46 | final double defaultHeight = 56; 47 | 48 | static const double centerMargin = 40; 49 | 50 | @override 51 | void initState() { 52 | super.initState(); 53 | 54 | controller = AnimationController( 55 | vsync: this, 56 | duration: Duration(milliseconds: 500), 57 | ); 58 | 59 | sizeAnim = Tween(begin: defaultHeight, end: 180) 60 | .animate( 61 | CurvedAnimation(parent: controller, curve: Curves.linear) 62 | ); 63 | } 64 | 65 | @override 66 | Widget build(BuildContext context) { 67 | final width = MediaQuery.of(context).size.width; 68 | 69 | return AnimatedBuilder( 70 | animation: controller, 71 | builder: (context, child) { 72 | return Container( 73 | width: width, 74 | height: sizeAnim.value, 75 | child: Stack( 76 | alignment: Alignment.bottomCenter, 77 | children: [ 78 | SlidingContainer(controller: controller, 79 | centerMargin: centerMargin, 80 | color: Colors.blue, 81 | ), 82 | 83 | ClipPath( 84 | clipper: BottomClipper(38.0), 85 | child: Container( 86 | height: defaultHeight, 87 | color: Colors.grey[200], 88 | ), 89 | ), 90 | 91 | Container( 92 | height: defaultHeight, 93 | padding: EdgeInsets.only(left: 16, right: 16), 94 | decoration: BoxDecoration( 95 | color: Colors.transparent, 96 | ), 97 | child: Row( 98 | children: [ 99 | Icon(Icons.home), 100 | Spacer(), 101 | Icon(Icons.credit_card), 102 | Spacer(), 103 | Spacer(), 104 | GestureDetector( 105 | onTap: () { 106 | if (controller.isCompleted) { 107 | controller.reverse(); 108 | } else { 109 | controller.forward(); 110 | } 111 | }, 112 | child: Container( 113 | width: 40, 114 | height: 40, 115 | margin: EdgeInsets.only(bottom: 40), 116 | child: Icon(Icons.add, color: Colors.black, size: 32,)), 117 | ), 118 | Spacer(), 119 | Spacer(), 120 | Icon(Icons.insert_drive_file), 121 | Spacer(), 122 | Icon(Icons.person), 123 | ], 124 | ), 125 | ), 126 | 127 | ], 128 | ), 129 | ); 130 | }, 131 | ); 132 | } 133 | } 134 | 135 | 136 | class SlidingContainer extends StatefulWidget { 137 | final Color color; 138 | final double centerMargin; 139 | final AnimationController controller; 140 | 141 | const SlidingContainer({Key key,this.color,this.centerMargin, this.controller}) 142 | : super(key: key); 143 | 144 | @override 145 | _SlidingContainerState createState() => _SlidingContainerState(); 146 | } 147 | 148 | class _SlidingContainerState 149 | extends State 150 | with SingleTickerProviderStateMixin{ 151 | 152 | double radialPercent = 30; 153 | Animation radiusAnimation; 154 | 155 | @override 156 | Widget build(BuildContext context) { 157 | final width = MediaQuery.of(context).size.width; 158 | 159 | radiusAnimation = Tween( 160 | begin: Offset(0, 0), 161 | end: Offset(width/2.4, 90) 162 | ).animate(CurvedAnimation(parent: widget.controller, curve: Curves.linear) 163 | ); 164 | 165 | return AnimatedBuilder( 166 | animation: widget.controller, 167 | builder: (context, child){ 168 | return ClipPath( 169 | clipper: MyClipper(radiusAnimation.value, widget.centerMargin), 170 | child: Container( 171 | color: widget.color, 172 | ), 173 | ); 174 | }, 175 | ); 176 | } 177 | 178 | } 179 | 180 | class MyClipper extends CustomClipper{ 181 | 182 | final double defaultMargin; 183 | final Offset radialPercent; 184 | MyClipper(this.radialPercent, this.defaultMargin); 185 | 186 | @override 187 | Path getClip(Size size) { 188 | final p = Path(); 189 | final height = size.height; 190 | final width = size.width; 191 | 192 | var radius = (height / width) + radialPercent.dx * 193 | radialPercent.dy / 100; 194 | 195 | 196 | var bottomCenter = Offset(width / 2, height - defaultMargin); 197 | p.addOval(Rect.fromCircle(center: bottomCenter, radius: radius)); 198 | 199 | return p; 200 | } 201 | 202 | @override 203 | bool shouldReclip(CustomClipper oldClipper) => true; 204 | } 205 | 206 | 207 | class BottomClipper extends CustomClipper{ 208 | final double radius; 209 | 210 | BottomClipper(this.radius); 211 | 212 | @override 213 | Path getClip(Size size) { 214 | final p = Path(); 215 | 216 | p.lineTo(0.0, size.height); 217 | p.lineTo(size.width, size.height); 218 | p.lineTo(size.width, 0.0); 219 | p.addOval(Rect.fromCircle(center: Offset(size.width/2, 0.0), radius: radius)); 220 | return p; 221 | } 222 | 223 | @override 224 | bool shouldReclip(CustomClipper oldClipper) => true; 225 | } -------------------------------------------------------------------------------- /lib/bottom_nav_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(App()); 4 | 5 | class App extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | // TODO: implement build 9 | return MaterialApp( 10 | title: 'Bottom Navy', 11 | home: HomePage(), 12 | ); 13 | } 14 | } 15 | 16 | class HomePage extends StatefulWidget { 17 | @override 18 | State createState() { 19 | return HomePageState(); 20 | } 21 | } 22 | 23 | class HomePageState extends State 24 | with SingleTickerProviderStateMixin { 25 | int _index = 0; 26 | TabController _controller; 27 | 28 | List pages = [ 29 | 'Page One', 30 | 'Page Two', 31 | 'Page Three', 32 | 'Page Four', 33 | ]; 34 | 35 | @override 36 | void initState() { 37 | super.initState(); 38 | _controller = TabController( 39 | vsync: this, 40 | length: pages.length, 41 | initialIndex: _index 42 | ); 43 | } 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return Scaffold( 48 | body: TabBarView( 49 | controller: _controller, 50 | children: pages.map((title) { 51 | return Center( 52 | child: Text( 53 | '$title', 54 | textAlign: TextAlign.center, 55 | style: TextStyle(fontSize: 52), 56 | ), 57 | ); 58 | }).toList(), 59 | ), 60 | appBar: AppBar( 61 | elevation: 1, 62 | title: Text("BottomNavyBar"), 63 | actions: [ 64 | Icon( 65 | Icons.more_vert, 66 | color: Colors.white, 67 | ), 68 | ], 69 | ), 70 | floatingActionButton: GestureDetector( 71 | onTap: (){ 72 | Navigator.push(context, 73 | MaterialPageRoute( 74 | fullscreenDialog: true, 75 | builder: (c)=> GDialog() 76 | ) 77 | ); 78 | }, 79 | child: GMenu(), 80 | ), 81 | 82 | ); 83 | } 84 | } 85 | 86 | class GMenu extends StatefulWidget { 87 | @override 88 | _GMenuState createState() => _GMenuState(); 89 | } 90 | class _GMenuState extends State { 91 | @override 92 | Widget build(BuildContext context) { 93 | return Container( 94 | width: 50, 95 | height: 50, 96 | decoration: BoxDecoration( 97 | color: Colors.white, 98 | borderRadius: BorderRadius.all(Radius.circular(50)), 99 | boxShadow: [ 100 | BoxShadow( 101 | color: Colors.black12, 102 | blurRadius: 15 103 | ) 104 | ] 105 | ), 106 | child: Padding( 107 | padding: EdgeInsets.symmetric(vertical: 14, horizontal: 10), 108 | child: Column( 109 | children: [ 110 | Hero( 111 | tag: '1', 112 | child: Container( 113 | color: Colors.orange, 114 | width: double.maxFinite, 115 | height: 5, 116 | ), 117 | ), 118 | Hero( 119 | tag: '2', 120 | child: Container( 121 | margin: EdgeInsets.only(top: 3, bottom: 3), 122 | color: Colors.blue, 123 | width: double.maxFinite, 124 | height: 5, 125 | ), 126 | ), 127 | Hero( 128 | tag: '3', 129 | child: Container( 130 | color: Colors.green, 131 | width: double.maxFinite, 132 | height: 5, 133 | ), 134 | ), 135 | ], 136 | ), 137 | ), 138 | ); 139 | } 140 | } 141 | 142 | class GDialog extends StatefulWidget { 143 | @override 144 | _GDialogState createState() => _GDialogState(); 145 | } 146 | 147 | class _GDialogState extends State { 148 | @override 149 | Widget build(BuildContext context) { 150 | return Scaffold( 151 | backgroundColor: Colors.white, 152 | body: Center( 153 | child: Container( 154 | height: 200, 155 | width: 300, 156 | child: Column( 157 | children: [ 158 | Hero( 159 | tag: '1', 160 | child: Material( 161 | color: Colors.transparent, 162 | child: Container( 163 | color: Colors.orange, 164 | width: double.maxFinite, 165 | height: 50, 166 | child: Center( 167 | child: Text("Settings"), 168 | ), 169 | ), 170 | ), 171 | ), 172 | Hero( 173 | tag: '2', 174 | child: Material( 175 | color: Colors.transparent, 176 | child: Container( 177 | margin: EdgeInsets.only(top: 20, bottom: 20), 178 | color: Colors.blue, 179 | width: double.maxFinite, 180 | height: 50, 181 | child: Center( 182 | child: Text("Messages"), 183 | ), 184 | ), 185 | ), 186 | ), 187 | Hero( 188 | tag: '3', 189 | child: Material( 190 | color: Colors.transparent, 191 | child: Container( 192 | color: Colors.green, 193 | width: double.maxFinite, 194 | height: 50, 195 | child: Center( 196 | child: Text("New Post"), 197 | ), 198 | ), 199 | ), 200 | ), 201 | ], 202 | ), 203 | ), 204 | ), 205 | ); 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /lib/bsd_login_register_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: "BSD Login & Register", 11 | theme: ThemeData(primarySwatch: Colors.green), 12 | home: HomePage(), 13 | ); 14 | } 15 | } 16 | 17 | class HomePage extends StatefulWidget { 18 | @override 19 | State createState() { 20 | return HomePageState(); 21 | } 22 | } 23 | 24 | class HomePageState extends State 25 | with SingleTickerProviderStateMixin { 26 | Animation slideUpAnimation; 27 | AnimationController slideUpAnimationController; 28 | 29 | @override 30 | void initState() { 31 | SystemChrome.setEnabledSystemUIOverlays([]); 32 | super.initState(); 33 | 34 | slideUpAnimationController = 35 | AnimationController(vsync: this, duration: Duration(milliseconds: 250)); 36 | } 37 | 38 | @override 39 | Widget build(BuildContext context) { 40 | slideUpAnimation = 41 | Tween(begin: MediaQuery.of(context).size.height / 1.2, end: 200) 42 | .animate(CurvedAnimation( 43 | parent: slideUpAnimationController, curve: Curves.linear)); 44 | 45 | return Scaffold( 46 | backgroundColor: Colors.deepPurple, 47 | body: Stack( 48 | children: [ 49 | AnimatedBuilder( 50 | animation: slideUpAnimationController, 51 | builder: (context, child) { 52 | return Positioned( 53 | top: slideUpAnimation.value, 54 | bottom: 0, 55 | child: Container( 56 | width: MediaQuery.of(context).size.width, 57 | decoration: BoxDecoration( 58 | color: Colors.white, 59 | borderRadius: 60 | BorderRadius.vertical(top: Radius.circular(100))), 61 | child: Center( 62 | child: Visibility( 63 | visible: !slideUpAnimationController.isAnimating && 64 | !slideUpAnimationController.isCompleted, 65 | child: GestureDetector( 66 | onTap: _onTap, 67 | onPanStart: null, 68 | child: Icon( 69 | Icons.arrow_upward, 70 | size: 50, 71 | ), 72 | ), 73 | replacement: Center( 74 | child: Text('Hello World!'), 75 | ), 76 | )), 77 | ), 78 | ); 79 | }, 80 | ) 81 | ], 82 | ), 83 | ); 84 | } 85 | /* 86 | void _onPanStart(DragStartDetails details) { 87 | startDragY = details.globalPosition.dy; 88 | startDragPercent = widget.sliderController.sliderValue; 89 | 90 | final sliderWidth = context.size.width; 91 | final sliderLeftPosition = 92 | (context.findRenderObject() as RenderBox).localToGlobal(const Offset(0.0, 0.0)).dx; 93 | final dragHorizontalPercent = (details.globalPosition.dx - sliderLeftPosition) / sliderWidth; 94 | 95 | widget.sliderController.onDragStart(dragHorizontalPercent); 96 | }*/ 97 | 98 | void _onTap() { 99 | setState(() { 100 | slideUpAnimationController.forward(); 101 | }); 102 | } 103 | } 104 | /* 105 | 106 | class _SliderDraggerState extends State { 107 | double startDragY; 108 | double startDragPercent; 109 | 110 | void _onPanStart(DragStartDetails details) { 111 | startDragY = details.globalPosition.dy; 112 | startDragPercent = widget.sliderController.sliderValue; 113 | 114 | final sliderWidth = context.size.width; 115 | final sliderLeftPosition = 116 | (context.findRenderObject() as RenderBox).localToGlobal(const Offset(0.0, 0.0)).dx; 117 | final dragHorizontalPercent = (details.globalPosition.dx - sliderLeftPosition) / sliderWidth; 118 | 119 | widget.sliderController.onDragStart(dragHorizontalPercent); 120 | } 121 | 122 | void _onPanUpdate(DragUpdateDetails details) { 123 | final dragDistance = startDragY - details.globalPosition.dy; 124 | final sliderHeight = context.size.height - widget.paddingTop - widget.paddingBottom; 125 | final dragPercent = dragDistance / sliderHeight; 126 | 127 | final sliderWidth = context.size.width; 128 | final sliderLeftPosition = 129 | (context.findRenderObject() as RenderBox).localToGlobal(const Offset(0.0, 0.0)).dx; 130 | final dragHorizontalPercent = (details.globalPosition.dx - sliderLeftPosition) / sliderWidth; 131 | 132 | widget.sliderController.draggingPercents = new Offset( 133 | dragHorizontalPercent, 134 | startDragPercent + dragPercent, 135 | ); 136 | } 137 | 138 | void _onPanEnd(DragEndDetails details) { 139 | startDragY = null; 140 | startDragPercent = null; 141 | 142 | widget.sliderController.onDragEnd(); 143 | } 144 | 145 | @override 146 | Widget build(BuildContext context) { 147 | return GestureDetector( 148 | onPanStart: _onPanStart, 149 | onPanUpdate: _onPanUpdate, 150 | onPanEnd: _onPanEnd, 151 | child: widget.child, 152 | ); 153 | } 154 | } 155 | */ 156 | -------------------------------------------------------------------------------- /lib/bubbles_rain.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/material.dart'; 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Bubble Rain', 11 | theme: ThemeData( 12 | primarySwatch: Colors.blue 13 | ), 14 | home: HomePage(), 15 | ); 16 | } 17 | } 18 | 19 | class HomePage extends StatefulWidget { 20 | 21 | @override 22 | _HomePageState createState() => _HomePageState(); 23 | } 24 | 25 | class _HomePageState extends State { 26 | 27 | double maxScreenWith; 28 | double maxScreenHeight; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | maxScreenWith = MediaQuery.of(context).size.width; 33 | maxScreenHeight = MediaQuery.of(context).size.height; 34 | final size = Size(maxScreenWith, maxScreenHeight); 35 | 36 | return Scaffold( 37 | body: Container( 38 | height: double.infinity, 39 | width: double.infinity, 40 | child: GameField(size), 41 | ), 42 | ); 43 | } 44 | } 45 | 46 | class Circle extends StatelessWidget { 47 | final Color color; 48 | final double _size = 50; 49 | 50 | const Circle({Key key, this.color = Colors.green}) 51 | : assert(color != null), 52 | super(key: key); 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | return Container( 57 | width: _size, 58 | height: _size, 59 | decoration: BoxDecoration( 60 | color: color, 61 | shape: BoxShape.circle 62 | ), 63 | ); 64 | } 65 | } 66 | class CircleController { 67 | } 68 | 69 | class GameField extends StatefulWidget { 70 | final Size size; 71 | GameField(this.size); 72 | 73 | @override 74 | _GameFieldState createState() => _GameFieldState(); 75 | } 76 | 77 | class _GameFieldState extends State { 78 | 79 | Size get size => widget.size; 80 | 81 | Size _randomPosition(Size size) { 82 | final x = Random().nextInt(size.width~/2); 83 | final y = Random().nextInt(size.height~/2); 84 | return Size(x.toDouble(), y.toDouble()); 85 | } 86 | 87 | addItem(){ 88 | 89 | } 90 | 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return Stack( 95 | children: [ 96 | 97 | Center(child: Circle(color: Colors.orange,),) 98 | ], 99 | ); 100 | } 101 | } -------------------------------------------------------------------------------- /lib/coffee_app_auth.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatefulWidget { 7 | @override 8 | _MyAppState createState() => _MyAppState(); 9 | } 10 | 11 | class _MyAppState extends State { 12 | 13 | @override 14 | void initState() { 15 | super.initState(); 16 | SystemChrome.setEnabledSystemUIOverlays([]); 17 | } 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | title: "Coffee App", 23 | home: AuthEntryPage(), 24 | ); 25 | } 26 | } 27 | 28 | enum AuthType { facebook, twitter, google, email } 29 | 30 | class AuthEntryPage extends StatelessWidget { 31 | 32 | final imageLinks = [ 33 | 'https://www.adamgault.co.uk/wp-content/uploads/2015/11/TradeIndustry038.jpg', 34 | 'https://img.etimg.com/thumb/msid-66650613,width-643,imgsize-801611,resizemode-4/coffee.jpg', 35 | 'https://img.etimg.com/thumb/msid-66650613,width-643,imgsize-801611,resizemode-4/coffee.jpg', 36 | ]; 37 | 38 | final authTypes = [ 39 | AuthType.facebook, 40 | AuthType.twitter, 41 | AuthType.google, 42 | AuthType.email 43 | ]; 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return Scaffold( 48 | body: SingleChildScrollView( 49 | child: Column( 50 | children: [ 51 | Container( 52 | width: double.infinity, 53 | height: MediaQuery.of(context).size.height /1.2, 54 | child: PageView( 55 | children: imageLinks.map((link) { 56 | return PageViewItem( 57 | imageUrl: link, 58 | ); 59 | }).toList(), 60 | ), 61 | ), 62 | 63 | Padding( 64 | padding: const EdgeInsets.symmetric(vertical: 16), 65 | child: Text("Sign in to continue".toUpperCase()), 66 | ), 67 | 68 | Row( 69 | mainAxisAlignment: MainAxisAlignment.center, 70 | children: authTypes.map((authType){ 71 | return _SocialButton( 72 | authType: authType, 73 | onPressed: () { 74 | if(authType == AuthType.email) { 75 | Navigator.push( 76 | context, 77 | MaterialPageRoute( 78 | builder: (_) => AuthPage() 79 | ) 80 | ); 81 | } 82 | }, 83 | ); 84 | }).toList(), 85 | ) 86 | ], 87 | ), 88 | ), 89 | ); 90 | } 91 | } 92 | 93 | class AuthPage extends StatefulWidget { 94 | 95 | @override 96 | _AuthPageState createState() => _AuthPageState(); 97 | } 98 | 99 | class _AuthPageState extends State 100 | with SingleTickerProviderStateMixin { 101 | TabController _tabController; 102 | int currentIndex = 0; 103 | 104 | @override 105 | void initState() { 106 | super.initState(); 107 | _tabController = TabController(length: 2, vsync: this); 108 | 109 | _tabController.addListener(() { 110 | setState(() { 111 | currentIndex = _tabController.index; 112 | }); 113 | }); 114 | } 115 | 116 | @override 117 | void dispose() { 118 | super.dispose(); 119 | _tabController.dispose(); 120 | } 121 | 122 | @override 123 | Widget build(BuildContext context) { 124 | return Scaffold( 125 | body: SingleChildScrollView( 126 | child: Column( 127 | children: [ 128 | Container( 129 | height: MediaQuery.of(context).size.height/2.1, 130 | width: double.infinity, 131 | margin: const EdgeInsets.symmetric(horizontal: 12), 132 | padding: const EdgeInsets.all(16), 133 | decoration: BoxDecoration( 134 | borderRadius: BorderRadius.only( 135 | bottomRight: Radius.circular(16), 136 | bottomLeft: Radius.circular(16) 137 | ), 138 | image: DecorationImage( 139 | fit: BoxFit.cover, 140 | image: NetworkImage('https://www.adamgault.co.uk/wp-content/uploads/2015/11/TradeIndustry038.jpg') 141 | ) 142 | ), 143 | child: Row( 144 | crossAxisAlignment: CrossAxisAlignment.end, 145 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 146 | children: [ 147 | Container( 148 | width: 50, 149 | height: 50, 150 | child: Icon( 151 | currentIndex == 0 ? Icons.person : Icons.group_add, 152 | color: Colors.white,), 153 | decoration: BoxDecoration( 154 | shape: BoxShape.circle, 155 | color: Theme.of(context).primaryColor 156 | ), 157 | ), 158 | SizedBox( 159 | width: 200, 160 | height: 40, 161 | child: TabBar( 162 | controller: _tabController, 163 | indicatorColor: Colors.white, 164 | indicatorSize: TabBarIndicatorSize.label, 165 | tabs: [ 166 | Text('Sign in'.toUpperCase()), 167 | Text('Sign up'.toUpperCase()) 168 | ], 169 | ), 170 | ) 171 | ], 172 | ), 173 | ), 174 | 175 | Container( 176 | height: MediaQuery.of(context).size.height/1.9, 177 | width: MediaQuery.of(context).size.width, 178 | child: TabBarView( 179 | controller: _tabController, 180 | physics: NeverScrollableScrollPhysics(), 181 | children: [ 182 | LoginContent(), 183 | RegistrationContent() 184 | ], 185 | ), 186 | ), 187 | ], 188 | ), 189 | ), 190 | ); 191 | } 192 | } 193 | 194 | class LoginContent extends StatelessWidget { 195 | @override 196 | Widget build(BuildContext context) { 197 | return Container( 198 | width: 200, 199 | height: 490, 200 | padding: const EdgeInsets.all(16), 201 | child: Column( 202 | children: [ 203 | const Spacer(), 204 | TextField( 205 | keyboardType: TextInputType.emailAddress, 206 | decoration: InputDecoration( 207 | hintText: 'Email Address', 208 | icon: Icon(Icons.email, color: Colors.brown,) 209 | ), 210 | ), 211 | Padding( 212 | padding: const EdgeInsets.only(top: 32), 213 | child: TextField( 214 | obscureText: true, 215 | decoration: InputDecoration( 216 | hintText: 'Password', 217 | icon: Icon(Icons.lock, color: Colors.brown,), 218 | suffixIcon: Text('Forgot?', style: TextStyle(color: Colors.grey),) 219 | ), 220 | ), 221 | ), 222 | 223 | const Spacer(), 224 | Align( 225 | alignment: Alignment.bottomRight, 226 | child: Row( 227 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 228 | children: [ 229 | GestureDetector( 230 | onTap: () => Navigator.pop(context), 231 | child: Row( 232 | children: [ 233 | Icon(Icons.arrow_back), 234 | Text('Social Login') 235 | ], 236 | ), 237 | ), 238 | GestureDetector( 239 | onTap: () {/*TODO: perform login operation*/}, 240 | child: Container( 241 | width: 50, 242 | height: 50, 243 | decoration: BoxDecoration( 244 | color: Colors.brown, 245 | shape: BoxShape.circle 246 | ), 247 | child: Center(child: 248 | Icon(Icons.arrow_forward, color: Colors.white,), 249 | ), 250 | ), 251 | ), 252 | ], 253 | ), 254 | ) 255 | ], 256 | ), 257 | ); 258 | } 259 | } 260 | 261 | class RegistrationContent extends StatelessWidget { 262 | @override 263 | Widget build(BuildContext context) { 264 | return Container( 265 | width: 200, 266 | height: 490, 267 | padding: const EdgeInsets.all(16), 268 | child: Column( 269 | children: [ 270 | const Spacer(), 271 | TextField( 272 | decoration: InputDecoration( 273 | hintText: 'Name', 274 | icon: Icon(Icons.person, color: Colors.brown,) 275 | ), 276 | ), 277 | Padding( 278 | padding: const EdgeInsets.symmetric(vertical: 32), 279 | child: TextField( 280 | keyboardType: TextInputType.emailAddress, 281 | decoration: InputDecoration( 282 | hintText: 'Email Address', 283 | icon: Icon(Icons.email, color: Colors.brown,) 284 | ), 285 | ), 286 | ), 287 | TextField( 288 | obscureText: true, 289 | decoration: InputDecoration( 290 | hintText: 'Password', 291 | icon: Icon(Icons.lock, color: Colors.brown,), 292 | suffixIcon: Text('Forgot?', style: TextStyle(color: Colors.grey),) 293 | ), 294 | ), 295 | 296 | const Spacer(), 297 | Align( 298 | alignment: Alignment.bottomRight, 299 | child: Row( 300 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 301 | children: [ 302 | GestureDetector( 303 | onTap: () => Navigator.pop(context), 304 | child: Row( 305 | children: [ 306 | Icon(Icons.arrow_back), 307 | Text('Social Login') 308 | ], 309 | ), 310 | ), 311 | GestureDetector( 312 | onTap: () {/*TODO: perform login operation*/}, 313 | child: Container( 314 | width: 50, 315 | height: 50, 316 | decoration: BoxDecoration( 317 | color: Colors.brown, 318 | shape: BoxShape.circle 319 | ), 320 | child: Center(child: 321 | Icon(Icons.arrow_forward, color: Colors.white,), 322 | ), 323 | ), 324 | ), 325 | ], 326 | ), 327 | ) 328 | ], 329 | ), 330 | ); 331 | } 332 | } 333 | 334 | 335 | 336 | 337 | class _SocialButton extends StatelessWidget { 338 | final AuthType authType; 339 | final VoidCallback onPressed; 340 | 341 | const _SocialButton({Key key, 342 | @required this.authType, 343 | @required this.onPressed 344 | }) : assert(authType != null), 345 | assert(onPressed != null); 346 | 347 | Widget _getChild() { 348 | switch(authType) { 349 | case AuthType.facebook: 350 | return Icon(Icons.camera); 351 | case AuthType.twitter: 352 | return Icon(Icons.wb_cloudy); 353 | case AuthType.google: 354 | return Icon(Icons.wb_sunny); 355 | case AuthType.email: 356 | return Text("Email".toUpperCase()); 357 | } 358 | throw Exception('Invalid Auth Type'); 359 | } 360 | 361 | @override 362 | Widget build(BuildContext context) { 363 | return GestureDetector( 364 | onTap: onPressed, 365 | child: Container( 366 | margin: const EdgeInsets.only(right: 16, left: 16), 367 | padding: const EdgeInsets.all(14), 368 | decoration: BoxDecoration( 369 | border: Border.all(), 370 | borderRadius: BorderRadius.circular(32) 371 | ), 372 | child: _getChild(), 373 | ), 374 | ); 375 | } 376 | } 377 | 378 | 379 | class PageViewItem extends StatelessWidget { 380 | final String imageUrl; 381 | 382 | const PageViewItem({Key key, 383 | @required this.imageUrl 384 | }) : assert(imageUrl != null), 385 | assert(imageUrl != ''); 386 | 387 | @override 388 | Widget build(BuildContext context) { 389 | return Container( 390 | padding: const EdgeInsets.all(16), 391 | margin: const EdgeInsets.fromLTRB(12, 12, 12, 0), 392 | decoration: BoxDecoration( 393 | color: Colors.black54, 394 | borderRadius: BorderRadius.circular(16), 395 | image: DecorationImage( 396 | fit: BoxFit.cover, 397 | image: NetworkImage(imageUrl) 398 | ) 399 | ), 400 | child: Column( 401 | crossAxisAlignment: CrossAxisAlignment.center, 402 | children: [ 403 | Text("Coffee Beans".toUpperCase(), 404 | style: TextStyle(color: Colors.white, fontSize: 42),), 405 | Text('Monthly Subscriptions'.toUpperCase(), 406 | style: TextStyle(color: Colors.white, fontSize: 18),), 407 | const Spacer(), 408 | Text('I am a coffee fanatic. Once you go to proper coffee you can\'t go back. You cannot go back.', 409 | style: TextStyle(color: Colors.white),), 410 | ], 411 | ), 412 | ); 413 | } 414 | } 415 | 416 | -------------------------------------------------------------------------------- /lib/crazy_switch_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: "Crazy Switch", 10 | home: HomePage(), 11 | ); 12 | } 13 | } 14 | 15 | class HomePage extends StatelessWidget { 16 | @override 17 | Widget build(BuildContext context) { 18 | return Scaffold( 19 | appBar: AppBar( 20 | title: Text("Crazy Switch"), 21 | backgroundColor: Colors.blue, 22 | ), 23 | body: Container( 24 | color: Colors.white, 25 | child: Center( 26 | child: CrazySwitch(), 27 | ), 28 | ), 29 | ); 30 | } 31 | } 32 | 33 | 34 | class CrazySwitch extends StatefulWidget { 35 | @override 36 | _CrazySwitchState createState() => _CrazySwitchState(); 37 | } 38 | 39 | class _CrazySwitchState extends 40 | State with 41 | SingleTickerProviderStateMixin { 42 | 43 | bool isChecked = false; 44 | Animation _animation; 45 | AnimationController _animationController; 46 | 47 | @override 48 | void initState() { 49 | _animationController = AnimationController( 50 | vsync: this, 51 | duration: Duration(milliseconds: 450) 52 | ); 53 | 54 | _animation = Tween( 55 | begin: Alignment.centerLeft, 56 | end: Alignment.centerRight 57 | ).animate( 58 | CurvedAnimation( 59 | parent: _animationController, 60 | curve: Curves.bounceIn, 61 | reverseCurve: Curves.bounceOut 62 | ) 63 | ); 64 | 65 | super.initState(); 66 | } 67 | 68 | @override 69 | Widget build(BuildContext context) { 70 | return AnimatedBuilder( 71 | animation: _animationController, 72 | builder: (animation, child){ 73 | return Container( 74 | width: 130, 75 | height: 60, 76 | decoration: BoxDecoration( 77 | color: isChecked ? Colors.green : Colors.red, 78 | borderRadius: BorderRadius.all( 79 | Radius.circular(32) 80 | ), 81 | boxShadow: [ 82 | BoxShadow( 83 | color: isChecked ? Colors.green : Colors.red, 84 | blurRadius: 15, 85 | offset: Offset(0, 15) 86 | ) 87 | ] 88 | ), 89 | child: Stack( 90 | children: [ 91 | Align( 92 | alignment: _animation.value, 93 | child: GestureDetector( 94 | onTap: (){ 95 | if(_animationController.isCompleted){ 96 | _animationController.reverse(); 97 | }else{ 98 | _animationController.forward(); 99 | } 100 | 101 | isChecked = !isChecked; 102 | }, 103 | child: Container( 104 | width: 48, 105 | height: 48, 106 | margin: EdgeInsets.only(left: 8, right: 8), 107 | decoration: BoxDecoration( 108 | shape: BoxShape.circle, 109 | color: Colors.white 110 | ), 111 | ), 112 | ), 113 | ) 114 | ], 115 | ), 116 | ); 117 | }, 118 | ); 119 | } 120 | } 121 | 122 | 123 | -------------------------------------------------------------------------------- /lib/flying_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/widgets.dart'; 4 | 5 | void main() => runApp(MyApp()); 6 | 7 | class MyApp extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | title: "Flying Item", 12 | home: HomePage(), 13 | ); 14 | } 15 | } 16 | 17 | class HomePage extends StatefulWidget { 18 | @override 19 | _HomePageState createState() => _HomePageState(); 20 | } 21 | 22 | class _HomePageState extends State 23 | with SingleTickerProviderStateMixin{ 24 | 25 | List items = List.generate(10, ((i){ return "Item $i"; })); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | backgroundColor: Colors.grey[200], 31 | appBar: AppBar( 32 | elevation: 1.1, 33 | backgroundColor: Colors.white, 34 | leading: Icon(Icons.menu, color: Colors.grey,), 35 | title: Center( 36 | child: Text("STORE", style: TextStyle( 37 | color: Colors.grey[500] 38 | ),), 39 | ), 40 | actions: [ 41 | Icon(Icons.search, color: Colors.grey) 42 | ], 43 | ), 44 | body: Container( 45 | width: MediaQuery.of(context).size.width, 46 | height: MediaQuery.of(context).size.height, 47 | child: ListView.builder( 48 | shrinkWrap: true, 49 | itemCount: items.length, 50 | itemBuilder: (c, ch){ 51 | return CartItem(); 52 | }, 53 | ), 54 | ), 55 | ); 56 | } 57 | 58 | } 59 | 60 | class CartItem extends StatefulWidget { 61 | @override 62 | _CartItemState createState() => _CartItemState(); 63 | } 64 | 65 | class _CartItemState extends State 66 | with TickerProviderStateMixin { 67 | 68 | 69 | Duration _duration = Duration(seconds: 2); 70 | 71 | double _size = 180; 72 | Animation _delayedAnimation; 73 | Animation _opacityAnimation; 74 | AnimationController _animationController; 75 | AnimationController _opacityController; 76 | 77 | @override 78 | void initState() { 79 | _animationController = AnimationController( 80 | vsync: this, 81 | duration: Duration(milliseconds: 2000) 82 | ); 83 | 84 | _opacityController = AnimationController( 85 | vsync: this, 86 | duration: Duration(milliseconds: 400) 87 | ); 88 | 89 | 90 | _opacityAnimation = Tween( 91 | begin: 1, //TODO: set this value back to 1 92 | end: 0 93 | ).animate( 94 | CurvedAnimation( 95 | parent: _opacityController, 96 | curve: Curves.linear 97 | ) 98 | )..addStatusListener((status){ 99 | if(status == AnimationStatus.completed){ 100 | _animationController.forward(); 101 | } 102 | }); 103 | super.initState(); 104 | } 105 | 106 | @override 107 | void dispose() { 108 | _animationController.dispose(); 109 | _opacityController.dispose(); 110 | super.dispose(); 111 | } 112 | 113 | @override 114 | Widget build(BuildContext context) { 115 | _delayedAnimation = Tween( 116 | begin: 10, 117 | end: MediaQuery.of(context).size.width 118 | ) 119 | .animate(CurvedAnimation( 120 | parent: _animationController, 121 | curve: Interval( 122 | 0.0, 1.0, 123 | curve: Curves.bounceInOut 124 | ) 125 | )) 126 | ..addStatusListener((status){ 127 | if(status == AnimationStatus.completed){ 128 | _size = 0; 129 | setState(() {}); 130 | } 131 | }); 132 | 133 | return GestureDetector( 134 | onTap: (){ 135 | _animationController.forward(); 136 | }, 137 | child: AnimatedContainer( 138 | duration: Duration(milliseconds: 200), 139 | width: 300, 140 | height: _size, 141 | child: Stack( 142 | alignment: Alignment.centerLeft, 143 | children: [ 144 | AnimatedBuilder( 145 | animation: _animationController, 146 | builder: (c, ch){ 147 | return Positioned( 148 | left: _delayedAnimation.value, 149 | child: Icon(Icons.shopping_cart, size: 90, color: Colors.redAccent,), 150 | ); 151 | }, 152 | ), 153 | 154 | AnimatedBuilder( 155 | animation: _opacityController, 156 | builder: (c, ch){ 157 | return Opacity( 158 | opacity: _opacityAnimation.value, 159 | child: Container( 160 | width: double.maxFinite, 161 | height: 200, 162 | padding: EdgeInsets.all(8), 163 | margin: EdgeInsets.all(8), 164 | decoration: BoxDecoration( 165 | color: Colors.white, 166 | borderRadius: BorderRadius.all(Radius.circular(12)), 167 | boxShadow: [ 168 | BoxShadow( 169 | color: Colors.grey[300], 170 | blurRadius: 1 171 | ) 172 | ] 173 | ), 174 | child: Row( 175 | children: [ 176 | Padding( 177 | padding: const EdgeInsets.only(right: 10), 178 | child: _buildImagePlaceHolder(), 179 | ), 180 | Column( 181 | crossAxisAlignment: CrossAxisAlignment.start, 182 | children: [ 183 | _buildRowPlaceHolder(), 184 | _buildRowPlaceHolder(width: 150), 185 | _buildRowPlaceHolder(width: 180), 186 | Spacer(), 187 | _buildButtonPlaceHolder() 188 | ], 189 | ), 190 | ], 191 | ), 192 | ), 193 | ); 194 | }, 195 | ), 196 | ], 197 | ), 198 | ), 199 | ); 200 | } 201 | 202 | Widget _buildButtonPlaceHolder(){ 203 | return Padding( 204 | padding: const EdgeInsets.only(left: 100), 205 | child: MaterialButton( 206 | elevation: 1, 207 | color: Colors.redAccent[100], 208 | onPressed: (){ 209 | _opacityController.forward(); 210 | }, 211 | ), 212 | ); 213 | } 214 | 215 | Widget _buildImagePlaceHolder(){ 216 | return ClipRRect( 217 | borderRadius: BorderRadius.all(Radius.circular(10)), 218 | child: Container( 219 | width: 125, 220 | height: double.maxFinite, 221 | color: Colors.grey[200], 222 | ), 223 | ); 224 | } 225 | 226 | Widget _buildRowPlaceHolder({double width = 120}){ 227 | return Container( 228 | width: width, 229 | height: 15, 230 | margin: EdgeInsets.all(2), 231 | decoration: BoxDecoration( 232 | color: Colors.grey[200], 233 | borderRadius: BorderRadius.all(Radius.circular(8)) 234 | ), 235 | ); 236 | } 237 | } 238 | 239 | -------------------------------------------------------------------------------- /lib/foldable_options_menu.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main()=> runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: "My App", 10 | home: HomePage(), 11 | ); 12 | } 13 | } 14 | 15 | class HomePage extends StatefulWidget { 16 | @override 17 | _HomePageState createState() => _HomePageState(); 18 | } 19 | 20 | class _HomePageState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return Scaffold( 24 | appBar: AppBar( 25 | title: Text("Foldable Options"), 26 | ), 27 | body: Stack( 28 | children: [ 29 | Align( 30 | alignment: Alignment.centerRight, 31 | child: FoldableOptions(), 32 | ), 33 | ], 34 | ), 35 | ); 36 | } 37 | } 38 | 39 | class FoldableOptions extends StatefulWidget { 40 | @override 41 | _FoldableOptionsState createState() => _FoldableOptionsState(); 42 | } 43 | 44 | class _FoldableOptionsState extends State with SingleTickerProviderStateMixin{ 45 | 46 | final List options =[ 47 | Icons.folder, 48 | Icons.share, 49 | Icons.visibility_off, 50 | Icons.star_border, 51 | Icons.notifications_none 52 | ]; 53 | 54 | Animation firstAnim; 55 | Animation secondAnim; 56 | Animation thirdAnim; 57 | Animation fourthAnim; 58 | Animation fifthAnim; 59 | Animation verticalPadding; 60 | AnimationController controller; 61 | final duration = Duration(milliseconds: 270); 62 | 63 | Widget getItem(IconData source){ 64 | final size = 40.0; 65 | return GestureDetector( 66 | onTap: (){ 67 | controller.reverse(); 68 | }, 69 | child: Container( 70 | width: size, 71 | height: size, 72 | decoration: BoxDecoration( 73 | color: Color(0XFF212121), 74 | borderRadius: BorderRadius.all(Radius.circular(30)) 75 | ), 76 | child: Icon(source, color: Colors.white, size: 18,), 77 | ), 78 | ); 79 | } 80 | 81 | Widget buildPrimaryItem(IconData source){ 82 | final size = 40.0; 83 | return Container( 84 | width: size, 85 | height: size, 86 | decoration: BoxDecoration( 87 | color: Colors.black, 88 | borderRadius: BorderRadius.all(Radius.circular(30)), 89 | boxShadow: [ 90 | BoxShadow( 91 | color: Colors.black87, 92 | blurRadius: verticalPadding.value 93 | ) 94 | ] 95 | ), 96 | child: Icon(source, color: Colors.white, size: 20 ,), 97 | ); 98 | } 99 | 100 | @override 101 | void initState() { 102 | super.initState(); 103 | controller = AnimationController(vsync: this, duration: duration); 104 | 105 | final anim = CurvedAnimation(parent: controller, curve: Curves.linear); 106 | firstAnim = Tween(begin: Alignment.centerRight, end: Alignment.topRight).animate( anim); 107 | secondAnim = Tween(begin: Alignment.centerRight, end: Alignment.topLeft).animate( anim); 108 | thirdAnim = Tween(begin: Alignment.centerRight, end: Alignment.centerLeft).animate( anim); 109 | fourthAnim = Tween(begin: Alignment.centerRight, end: Alignment.bottomLeft).animate( anim); 110 | fifthAnim = Tween(begin: Alignment.centerRight, end: Alignment.bottomRight).animate( anim); 111 | verticalPadding = Tween(begin: 0, end: 26).animate( anim); 112 | } 113 | 114 | @override 115 | Widget build(BuildContext context) { 116 | return Container( 117 | width: 150, 118 | height: 200, 119 | margin: EdgeInsets.only(right: 2), 120 | child: AnimatedBuilder( 121 | animation: controller, 122 | builder: (context, child){ 123 | return Stack( 124 | children: [ 125 | Align(alignment: firstAnim.value, child: getItem(options.elementAt(0)),), 126 | Align( 127 | alignment: secondAnim.value, 128 | child: Container( 129 | padding: EdgeInsets.only(left: 50, top: verticalPadding.value), 130 | child: getItem(options.elementAt(1))) 131 | ), 132 | 133 | Align(alignment: thirdAnim.value, child: getItem(options.elementAt(2))), 134 | Align(alignment: fourthAnim.value, 135 | child: Container( 136 | padding: EdgeInsets.only(left: 50, bottom: verticalPadding.value), 137 | child: getItem(options.elementAt(3)), 138 | ) 139 | ), 140 | Align(alignment: fifthAnim.value, child: getItem(options.elementAt(4))), 141 | Align( 142 | alignment: Alignment.centerRight, 143 | child: GestureDetector( 144 | onTap: (){ 145 | controller.isCompleted ? controller.reverse() : controller.forward(); 146 | }, 147 | child: buildPrimaryItem(controller.isCompleted || controller.isAnimating? Icons.close : Icons.add)), 148 | ) 149 | ], 150 | ); 151 | }, 152 | ), 153 | ); 154 | } 155 | } -------------------------------------------------------------------------------- /lib/grid_list_example.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp( MyApp()); 4 | 5 | class MyApp extends StatelessWidget{ 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: 'Grid List', 10 | home: MainPage(), 11 | ); 12 | } 13 | } 14 | 15 | 16 | class MainPage extends StatefulWidget { 17 | @override 18 | _MainPageState createState() => _MainPageState(); 19 | } 20 | 21 | class _MainPageState extends State { 22 | @override 23 | Widget build(BuildContext context) { 24 | return Scaffold( 25 | appBar: AppBar( 26 | title: Text('Grid Sample'), 27 | ), 28 | body: GridView.count( 29 | crossAxisCount: 2, 30 | scrollDirection: Axis.vertical, 31 | children: List.generate(8, (index){ 32 | return Container( 33 | color: Colors.primaries[index], 34 | child: Center( 35 | child: Text('Item ${index+1}'), 36 | ), 37 | ); 38 | }), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/indexed_list.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/cupertino.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'dart:math' as math; 6 | 7 | import 'package:flutter/foundation.dart'; 8 | import 'package:flutter/rendering.dart'; 9 | 10 | void main() => runApp(MyApp()); 11 | 12 | class MyApp extends StatelessWidget { 13 | @override 14 | Widget build(BuildContext context) { 15 | return MaterialApp( 16 | title: 'Flutter Demo', 17 | theme: ThemeData( 18 | primarySwatch: Colors.blue, 19 | ), 20 | home: MyHomePage(title: 'Flutter Demo Home Page'), 21 | ); 22 | } 23 | } 24 | 25 | class MyHomePage extends StatefulWidget { 26 | MyHomePage({Key key, this.title}) : super(key: key); 27 | final String title; 28 | 29 | @override 30 | _MyHomePageState createState() => _MyHomePageState(); 31 | } 32 | 33 | class _MyHomePageState extends State with SingleTickerProviderStateMixin { 34 | 35 | final List categories = ['Top stories', 'Design', 'Business', 'Auto']; 36 | List> buildData(){ 37 | return List.generate(5, (index){ 38 | return List.generate(5, (i){ 39 | return "Item $i"; 40 | }); 41 | }); 42 | } 43 | 44 | ScrollController controller; 45 | AnimationController _animationController; 46 | Animation animation; 47 | 48 | int s = 0; 49 | 50 | @override 51 | void initState() { 52 | super.initState(); 53 | 54 | controller = ScrollController(); 55 | controller.addListener((){ 56 | var offset = controller.offset; 57 | print('OFFSET> $offset'); 58 | 59 | if(offset == 0){ 60 | _animationController.forward(); 61 | return; 62 | } else if (offset > 0 && _animationController.isCompleted) { 63 | _animationController.reverse(); 64 | } 65 | }); 66 | 67 | _animationController = AnimationController( 68 | vsync: this, 69 | duration: Duration(milliseconds: 500) 70 | ); 71 | 72 | animation = Tween( 73 | begin: 0, end: 200 74 | ).animate(CurvedAnimation(parent: _animationController, curve: Curves.linear)); 75 | 76 | } 77 | 78 | 79 | @override 80 | Widget build(BuildContext context) { 81 | return Scaffold( 82 | backgroundColor: Colors.grey[200], 83 | body: Stack( 84 | children: [ 85 | AnimatedBuilder( 86 | animation: _animationController, 87 | builder: (context, child){ 88 | return Container( 89 | margin: EdgeInsets.only(top: animation.value), 90 | child: _buildContent(), 91 | ); 92 | }, 93 | ), 94 | ], 95 | ), // This trailing comma makes auto-formatting nicer for build methods. 96 | ); 97 | } 98 | 99 | Widget _buildContent() { 100 | return ListView.builder( 101 | controller: controller, 102 | itemCount: categories.length, 103 | itemBuilder: (BuildContext context, index) { 104 | var subList = buildData().elementAt(index); 105 | 106 | return ListItem( 107 | isLastItem: (categories.length - 1) == index, 108 | data: categories.elementAt(index), 109 | secondaryListData: subList.map((title) { 110 | return SubItemModel( 111 | title: title, 112 | description: '${index * 2}min ago' 113 | ); 114 | }).toList(), 115 | ); 116 | }, 117 | ); 118 | } 119 | } 120 | 121 | 122 | class ListItem extends StatefulWidget { 123 | 124 | final String data; 125 | final bool isLastItem; 126 | final List secondaryListData; 127 | const ListItem({ 128 | Key key, 129 | this.secondaryListData, 130 | this.data, 131 | this.isLastItem 132 | }) : super(key: key); 133 | 134 | @override 135 | _ListItemState createState() => _ListItemState(); 136 | } 137 | 138 | class _ListItemState extends State { 139 | 140 | final String divider = '...'; 141 | final double height = 200; 142 | final double primaryListWidth = 60; 143 | 144 | FixedExtentScrollController controller; 145 | 146 | @override 147 | void initState(){ 148 | super.initState(); 149 | 150 | controller = FixedExtentScrollController( 151 | initialItem: 0 152 | ); 153 | } 154 | 155 | Widget _buildTitleItem(String data) { 156 | return RotatedBox( 157 | quarterTurns: (180.0 - pi / 180.0).toInt(), 158 | child: Container( 159 | child: Center( 160 | child: Text(data, style: TextStyle( 161 | fontSize: 18, 162 | fontWeight: data == "..." ? FontWeight.bold : null 163 | ), 164 | ), 165 | ), 166 | ), 167 | ); 168 | } 169 | 170 | @override 171 | Widget build(BuildContext context) { 172 | return Container( 173 | width: MediaQuery.of(context).size.width, 174 | height: height, 175 | child: Row( 176 | children: [ 177 | Container( 178 | color: Colors.white, 179 | padding: EdgeInsets.only(top: 24, bottom: 24), 180 | width: primaryListWidth, 181 | child: Column( 182 | mainAxisAlignment: MainAxisAlignment.center, 183 | children: [ 184 | _buildTitleItem(widget.data), 185 | widget.isLastItem ? Container() : Spacer(), 186 | widget.isLastItem? Container() : _buildTitleItem("..."), 187 | ], 188 | ) 189 | ), 190 | Container( 191 | color: Colors.grey[100], 192 | margin: EdgeInsets.only(bottom: 1.5), 193 | width: MediaQuery.of(context).size.width - primaryListWidth, 194 | child: ListWheelScrollView( 195 | itemExtent: (height/2.6)/1*0.9, 196 | controller: controller, 197 | diameterRatio: 25.1, 198 | physics: FixedExtentScrollPhysics(), 199 | children: widget.secondaryListData.map((item){ 200 | return ChildListItemWidget( 201 | parentHeight: height, 202 | item: item, 203 | ); 204 | }).toList(), 205 | ) , 206 | ), 207 | ], 208 | ), 209 | ); 210 | } 211 | 212 | } 213 | 214 | 215 | class ChildListItemWidget extends StatelessWidget{ 216 | 217 | final SubItemModel item; 218 | final double parentHeight; 219 | const ChildListItemWidget({ 220 | Key key, 221 | this.item, 222 | this.parentHeight 223 | }) : super(key: key); 224 | 225 | @override 226 | Widget build(BuildContext context) { 227 | return Container( 228 | height: parentHeight/2.5, 229 | padding: EdgeInsets.only(top: 8,bottom: 8, left: 32), 230 | child: Row( 231 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 232 | children: [ 233 | Column( 234 | mainAxisSize: MainAxisSize.min, 235 | crossAxisAlignment: CrossAxisAlignment.start, 236 | children: [ 237 | Text(item.title, style: TextStyle( 238 | fontSize: 18, 239 | fontWeight: FontWeight.bold 240 | ),), 241 | Padding( 242 | padding: const EdgeInsets.only(top: 4), 243 | child: Text(item.description, style: TextStyle( 244 | ),), 245 | ), 246 | ], 247 | ), 248 | 249 | Container( 250 | width: 50, 251 | height: 50, 252 | decoration: BoxDecoration( 253 | color: Colors.blue, 254 | borderRadius: BorderRadius.only( 255 | topLeft: Radius.circular(6), 256 | bottomLeft: Radius.circular(6) 257 | ) 258 | ), 259 | ) 260 | ], 261 | ), 262 | ); 263 | } 264 | } 265 | 266 | class SubItemModel{ 267 | final String title; 268 | final String description; 269 | final String imageUrl; 270 | 271 | SubItemModel({this.title, this.description, this.imageUrl}); 272 | } 273 | 274 | 275 | 276 | 277 | /// A working sample in progress... 278 | class _MyHomePageState_ extends State { 279 | 280 | @override 281 | Widget build(BuildContext context) { 282 | 283 | return Scaffold( 284 | appBar: AppBar( 285 | title: Text(widget.title), 286 | ), 287 | body: Stack( 288 | children: [ 289 | Center( 290 | child: Container( 291 | width: MediaQuery.of(context).size.width, 292 | height: 200, 293 | color: Colors.black12, 294 | child: NumberSelector( 295 | color: Colors.pink, 296 | ), 297 | ), 298 | ) 299 | ], 300 | ),// This trailing comma makes auto-formatting nicer for build methods. 301 | ); 302 | } 303 | 304 | } 305 | 306 | 307 | 308 | 309 | class NumberSelector extends StatefulWidget { 310 | final Color color; 311 | 312 | NumberSelector({Key key, 313 | this.color, 314 | }) : super(key: key); 315 | 316 | @override 317 | _NumberSelectorState createState() => _NumberSelectorState(); 318 | } 319 | 320 | class _NumberSelectorState extends State { 321 | 322 | double sliderPercent = 100; 323 | double startDragPercent; 324 | double startDragX; 325 | bool isAnimating = false; 326 | Size size; 327 | 328 | @override 329 | Widget build(BuildContext context) { 330 | size = MediaQuery.of(context).size; 331 | final width = size.width; 332 | final height = size.height; 333 | 334 | return Stack( 335 | children: [ 336 | ClipPath( 337 | clipper: MarksClipper( 338 | sliderPercent: sliderPercent, 339 | isAnimating: isAnimating 340 | ), 341 | child: Container( 342 | width: width, 343 | height: 200, 344 | color: Colors.pink[400], 345 | ) 346 | ), 347 | 348 | GestureDetector( 349 | onHorizontalDragStart: _horizontalDragStart, 350 | onHorizontalDragUpdate: _horizontalDragUpdate, 351 | onHorizontalDragEnd: _horizontalDragEnd, 352 | child: ClipPath( 353 | clipper: CircleClipper( 354 | sliderPercent: sliderPercent 355 | ), 356 | child: Container( 357 | color: Color(0XFF212121), 358 | ), 359 | ), 360 | ) 361 | ], 362 | ); 363 | } 364 | 365 | void _horizontalDragStart(DragStartDetails details) { 366 | isAnimating = true; 367 | startDragX = details.globalPosition.dx; 368 | startDragPercent = (sliderPercent-startDragX); 369 | } 370 | 371 | void _horizontalDragUpdate(DragUpdateDetails details) { 372 | isAnimating = true; 373 | final distance = startDragX + details.globalPosition.dx; 374 | final sliderWidth = size.width; 375 | final mDragPercent = distance / sliderWidth; 376 | 377 | // Testing 378 | final mPercent = startDragPercent + mDragPercent * 379 | details.globalPosition.distance/1.7; 380 | 381 | print('PERCENT: $mPercent'); 382 | 383 | setState(() { 384 | // Testing 385 | sliderPercent = mPercent; 386 | 387 | //sliderPercent = startDragPercent + mDragPercent * details.globalPosition.distance/50.5; 388 | }); 389 | } 390 | 391 | void _horizontalDragEnd(DragEndDetails details) { 392 | isAnimating = false; 393 | startDragX = null; 394 | startDragPercent = null; 395 | 396 | } 397 | } 398 | 399 | 400 | 401 | class CircleClipper extends CustomClipper{ 402 | final double sliderPercent; 403 | final double radius = 20; 404 | 405 | CircleClipper({this.sliderPercent}); 406 | 407 | @override 408 | Path getClip(Size size) { 409 | final p = Path(); 410 | //final positionY = size.height-radius; //TODO: remove this line 411 | final positionY = size.height/2+radius*1.5; 412 | 413 | p.addOval(Rect.fromCircle( 414 | center: Offset(sliderPercent, positionY), 415 | radius: radius 416 | )); 417 | 418 | return p; 419 | } 420 | 421 | @override 422 | bool shouldReclip(CustomClipper oldClipper) => true; 423 | } 424 | 425 | class MarksClipper extends CustomClipper { 426 | 427 | final double sliderPercent; 428 | final bool isAnimating; 429 | 430 | MarksClipper({ 431 | this.sliderPercent, 432 | this.isAnimating 433 | }); 434 | 435 | 436 | @override 437 | Path getClip(Size size) { 438 | final path = Path(); 439 | 440 | final elevation = isAnimating ? 10 : 0; 441 | final circlePosiX = isAnimating ? sliderPercent : size.width; 442 | 443 | final strokeSize = size.height/2-5; 444 | 445 | //print("strokeSize: $strokeSize"); 446 | 447 | path.lineTo(0, size.height-strokeSize); 448 | //path.quadraticBezierTo(size.width-sliderPercent, size.height-strokeSize-elevation, size.width, size.height-strokeSize); 449 | 450 | path.quadraticBezierTo(circlePosiX, size.height-strokeSize-elevation, 451 | size.width, size.height-strokeSize+elevation); 452 | 453 | 454 | 455 | path.lineTo(size.width, strokeSize); 456 | path.lineTo(0, strokeSize); 457 | path.close(); 458 | 459 | return path; 460 | } 461 | 462 | @override 463 | bool shouldReclip(CustomClipper oldClipper) { 464 | return true; 465 | } 466 | } -------------------------------------------------------------------------------- /lib/liquid_swipe_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp(LiquidApp()); 5 | 6 | class LiquidApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Liquid Swipe', 11 | theme: ThemeData(primarySwatch: Colors.red), 12 | home: HomePage(), 13 | ); 14 | } 15 | } 16 | 17 | class HomePage extends StatefulWidget { 18 | @override 19 | State createState() { 20 | return HomePageState(); 21 | } 22 | } 23 | 24 | class HomePageState extends State { 25 | 26 | Widget _buildChild(){ 27 | return Text('Liquid Swipe', 28 | style: TextStyle( 29 | fontSize: 36, 30 | color: Colors.white 31 | ), 32 | ); 33 | } 34 | 35 | @override 36 | void initState() { 37 | SystemChrome.setEnabledSystemUIOverlays([]); 38 | super.initState(); 39 | } 40 | 41 | @override 42 | Widget build(BuildContext context) { 43 | return Scaffold( 44 | body: Stack( 45 | children: [ 46 | CustomContainer( 47 | MediaQuery.of(context).size, 48 | Container( 49 | color: Colors.purple, 50 | child: Center(child: _buildChild(),), 51 | ) 52 | ), 53 | //CustomContainer( Colors.orange), 54 | ], 55 | ), 56 | ); 57 | } 58 | } 59 | 60 | class CustomContainer extends StatefulWidget { 61 | final Size mSize; 62 | final Widget child; 63 | 64 | CustomContainer(this.mSize, this.child); 65 | 66 | @override 67 | State createState() { 68 | return CustomContainerState(); 69 | } 70 | } 71 | 72 | class CustomContainerState 73 | extends State 74 | with SingleTickerProviderStateMixin { 75 | 76 | Animation animation; 77 | AnimationController controller; 78 | double sliderPercent = 30; 79 | double startDragPercent; 80 | double startDragX; 81 | 82 | @override 83 | void initState() { 84 | super.initState(); 85 | 86 | controller = AnimationController( 87 | vsync: this, 88 | duration: Duration(milliseconds: 700) 89 | ); 90 | 91 | } 92 | 93 | @override 94 | Widget build(BuildContext context) { 95 | final height = MediaQuery.of(context).size.height; 96 | final width = MediaQuery.of(context).size.width; 97 | 98 | animation = Tween( 99 | begin: sliderPercent, 100 | end: width 101 | ).animate( 102 | CurvedAnimation(parent: controller, curve: Curves.linear) 103 | ); 104 | 105 | return GestureDetector( 106 | onHorizontalDragStart: _horizontalDragStart, 107 | onHorizontalDragUpdate: _horizontalDragUpdate, 108 | onHorizontalDragEnd: _horizontalDragEnd, 109 | child: AnimatedBuilder( 110 | animation: controller, 111 | builder: (con, c) { 112 | return ClipPath( 113 | clipper: MyClipper(animation.value), 114 | child: widget.child, 115 | ); 116 | }, 117 | ), 118 | ); 119 | } 120 | 121 | void _horizontalDragStart(DragStartDetails details) { 122 | startDragX = details.globalPosition.dx; 123 | startDragPercent = sliderPercent; 124 | } 125 | 126 | void _horizontalDragUpdate(DragUpdateDetails details) { 127 | final distance = startDragX - details.globalPosition.dx; 128 | final sliderWidth = widget.mSize.width; 129 | final mDragPercent = distance / sliderWidth; 130 | 131 | setState(() { 132 | sliderPercent = startDragPercent + mDragPercent * 133 | details.globalPosition.distance/1.5; 134 | }); 135 | } 136 | 137 | void _horizontalDragEnd(DragEndDetails details) { 138 | startDragX = null; 139 | startDragPercent = null; 140 | 141 | setState(() { 142 | //controller.forward(); 143 | }); 144 | 145 | } 146 | } 147 | 148 | class MyClipper extends CustomClipper { 149 | final double sliderPercent; 150 | 151 | MyClipper(this.sliderPercent); 152 | 153 | @override 154 | Path getClip(Size size) { 155 | var path = Path(); 156 | 157 | // colored background 158 | path.addRect( 159 | Rect.fromLTRB( 160 | size.width - sliderPercent, 161 | 0, 162 | size.width, 163 | size.height 164 | ), 165 | ); 166 | 167 | path.close(); 168 | return path; 169 | } 170 | 171 | @override 172 | bool shouldReclip(CustomClipper oldClipper) => true; 173 | } 174 | -------------------------------------------------------------------------------- /lib/login_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp(LoginApp()); 5 | 6 | class LoginApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Login Challenge', 11 | theme: ThemeData( 12 | primarySwatch: Colors.deepPurple 13 | ), 14 | home: LoginPage(), 15 | ); 16 | } 17 | } 18 | 19 | class LoginPage extends StatefulWidget { 20 | @override 21 | State createState() { 22 | return _LoginPageState(); 23 | } 24 | } 25 | 26 | class _LoginPageState extends State { 27 | 28 | // f45d27 29 | // f5851f 30 | 31 | @override 32 | void initState() { 33 | SystemChrome.setEnabledSystemUIOverlays([]); 34 | super.initState(); 35 | } 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Scaffold( 40 | body: Container( 41 | child: Column( 42 | children: [ 43 | Container( 44 | width: MediaQuery.of(context).size.width, 45 | height: MediaQuery.of(context).size.height/2.5, 46 | decoration: BoxDecoration( 47 | gradient: LinearGradient( 48 | begin: Alignment.topCenter, 49 | end: Alignment.bottomCenter, 50 | colors: [ 51 | Color(0xFFf45d27), 52 | Color(0xFFf5851f) 53 | ], 54 | ), 55 | borderRadius: BorderRadius.only( 56 | bottomLeft: Radius.circular(90) 57 | ) 58 | ), 59 | child: Column( 60 | mainAxisAlignment: MainAxisAlignment.center, 61 | children: [ 62 | Spacer(), 63 | Align( 64 | alignment: Alignment.center, 65 | child: Icon(Icons.person, 66 | size: 90, 67 | color: Colors.white, 68 | ), 69 | ), 70 | Spacer(), 71 | 72 | Align( 73 | alignment: Alignment.bottomRight, 74 | child: Padding( 75 | padding: const EdgeInsets.only( 76 | bottom: 32, 77 | right: 32 78 | ), 79 | child: Text('Login', 80 | style: TextStyle( 81 | color: Colors.white, 82 | fontSize: 18 83 | ), 84 | ), 85 | ), 86 | ), 87 | ], 88 | ), 89 | ), 90 | 91 | Container( 92 | height: MediaQuery.of(context).size.height/2, 93 | width: MediaQuery.of(context).size.width, 94 | padding: EdgeInsets.only(top: 62), 95 | child: Column( 96 | children: [ 97 | Container( 98 | width: MediaQuery.of(context).size.width/1.2, 99 | height: 45, 100 | padding: EdgeInsets.only( 101 | top: 4,left: 16, right: 16, bottom: 4 102 | ), 103 | decoration: BoxDecoration( 104 | borderRadius: BorderRadius.all( 105 | Radius.circular(50) 106 | ), 107 | color: Colors.white, 108 | boxShadow: [ 109 | BoxShadow( 110 | color: Colors.black12, 111 | blurRadius: 5 112 | ) 113 | ] 114 | ), 115 | child: TextField( 116 | decoration: InputDecoration( 117 | border: InputBorder.none, 118 | icon: Icon(Icons.email, 119 | color: Colors.grey, 120 | ), 121 | hintText: 'Email', 122 | ), 123 | ), 124 | ), 125 | Container( 126 | width: MediaQuery.of(context).size.width/1.2, 127 | height: 45, 128 | margin: EdgeInsets.only(top: 32), 129 | padding: EdgeInsets.only( 130 | top: 4,left: 16, right: 16, bottom: 4 131 | ), 132 | decoration: BoxDecoration( 133 | borderRadius: BorderRadius.all( 134 | Radius.circular(50) 135 | ), 136 | color: Colors.white, 137 | boxShadow: [ 138 | BoxShadow( 139 | color: Colors.black12, 140 | blurRadius: 5 141 | ) 142 | ] 143 | ), 144 | child: TextField( 145 | decoration: InputDecoration( 146 | border: InputBorder.none, 147 | icon: Icon(Icons.vpn_key, 148 | color: Colors.grey, 149 | ), 150 | hintText: 'Password', 151 | ), 152 | ), 153 | ), 154 | 155 | Align( 156 | alignment: Alignment.centerRight, 157 | child: Padding( 158 | padding: const EdgeInsets.only( 159 | top: 16, right: 32 160 | ), 161 | child: Text('Forgot Password ?', 162 | style: TextStyle( 163 | color: Colors.grey 164 | ), 165 | ), 166 | ), 167 | ), 168 | Spacer(), 169 | 170 | Container( 171 | height: 45, 172 | width: MediaQuery.of(context).size.width/1.2, 173 | decoration: BoxDecoration( 174 | gradient: LinearGradient( 175 | colors: [ 176 | Color(0xFFf45d27), 177 | Color(0xFFf5851f) 178 | ], 179 | ), 180 | borderRadius: BorderRadius.all( 181 | Radius.circular(50) 182 | ) 183 | ), 184 | child: Center( 185 | child: Text('Login'.toUpperCase(), 186 | style: TextStyle( 187 | color: Colors.white, 188 | fontWeight: FontWeight.bold 189 | ), 190 | ), 191 | ), 192 | ), 193 | ], 194 | ), 195 | ) 196 | ], 197 | ), 198 | ), 199 | ); 200 | } 201 | } -------------------------------------------------------------------------------- /lib/login_profile_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main(){ 4 | runApp(MyApp()); 5 | } 6 | 7 | class MyApp extends StatelessWidget { 8 | @override 9 | Widget build(BuildContext context) { 10 | return MaterialApp( 11 | title: "Login & Register", 12 | home: LoginPage(), 13 | ); 14 | } 15 | } 16 | 17 | class LoginPage extends StatelessWidget { 18 | @override 19 | Widget build(BuildContext context) { 20 | return Scaffold( 21 | backgroundColor: Colors.deepPurple, 22 | appBar: AppBar( 23 | elevation: 0, 24 | backgroundColor: Colors.transparent, 25 | leading: BackButton(), 26 | ), 27 | body: Stack( 28 | children: [ 29 | Positioned( 30 | bottom: 0, 31 | left: 0, 32 | right: 0, 33 | top: 0, 34 | child: ClipRRect( 35 | borderRadius: BorderRadius.only( 36 | topLeft: Radius.circular(32), 37 | topRight: Radius.circular(32) 38 | ), 39 | child: Container( 40 | color: Colors.white, 41 | padding: EdgeInsets.fromLTRB(16, 32, 16, 32), 42 | child: Column( 43 | crossAxisAlignment: CrossAxisAlignment.start, 44 | children: [ 45 | Text("Login Now", style: TextStyle( 46 | color: Colors.blueGrey, 47 | fontSize: 32, 48 | fontWeight: FontWeight.bold 49 | ), 50 | ), 51 | Text("Please login to continue using our app.", 52 | style: TextStyle( 53 | color: Colors.blueGrey 54 | ), 55 | ), 56 | SizedBox(height: 90,), 57 | Text("Email ID"), 58 | SizedBox(height: 10,), 59 | Material( 60 | elevation: 4, 61 | borderRadius: BorderRadius.all( 62 | Radius.circular(32), 63 | ), 64 | child: TextField( 65 | decoration: InputDecoration( 66 | border: InputBorder.none 67 | ), 68 | ), 69 | ), 70 | 71 | SizedBox(height: 32,), 72 | Text("Password"), 73 | SizedBox(height: 10,), 74 | Material( 75 | elevation: 4, 76 | borderRadius: BorderRadius.circular(32), 77 | child: TextField( 78 | decoration: InputDecoration( 79 | border: InputBorder.none 80 | ), 81 | ), 82 | ), 83 | Align( 84 | alignment: Alignment.centerRight, 85 | child: Padding( 86 | padding: const EdgeInsets.only(top: 16), 87 | child: Text("Forgot your password?", 88 | style: TextStyle( 89 | color: Colors.deepPurple 90 | ), 91 | ), 92 | ), 93 | ), 94 | 95 | MaterialButton( 96 | shape: BeveledRectangleBorder( 97 | side: BorderSide( 98 | width: 16.0, color: Colors.lightBlue.shade50 99 | ), 100 | borderRadius: BorderRadius.circular(32) 101 | ), 102 | minWidth: double.maxFinite, 103 | color: Colors.deepPurple, 104 | onPressed: (){}, 105 | child: Text("Login"), 106 | ) 107 | ], 108 | ), 109 | ), 110 | ), 111 | ), 112 | ], 113 | ), 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'banking_app.dart'; 4 | 5 | void main() { 6 | runApp( 7 | MaterialApp( 8 | debugShowCheckedModeBanner: false, 9 | home: BankApp(), 10 | ), 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /lib/minimal_login.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp( MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | home: LoginPage(), 11 | ); 12 | } 13 | } 14 | 15 | class LoginPage extends StatefulWidget { 16 | @override 17 | _LoginPageState createState() => _LoginPageState(); 18 | } 19 | 20 | class _LoginPageState extends State { 21 | 22 | @override 23 | void initState() { 24 | SystemChrome.setEnabledSystemUIOverlays([]); 25 | super.initState(); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | body: Container( 32 | width: double.maxFinite, 33 | height: double.maxFinite, 34 | child: Stack( 35 | children: [ 36 | Positioned( 37 | top: 0, 38 | bottom: MediaQuery.of(context).size.height/2, 39 | child: Image.asset( 40 | "images/martian_surface.png", 41 | ), 42 | ), 43 | 44 | Positioned( 45 | top: 100, 46 | left: 32, 47 | child: Text('Sign in', 48 | style: TextStyle( 49 | fontSize: 24, 50 | fontWeight: FontWeight.bold, 51 | color: Colors.white 52 | ), 53 | ), 54 | ), 55 | 56 | Positioned( 57 | top: 190, 58 | child: Container( 59 | padding: EdgeInsets.all(32), 60 | width: MediaQuery.of(context).size.width, 61 | height: MediaQuery.of(context).size.height, 62 | decoration: BoxDecoration( 63 | color: Colors.white, 64 | borderRadius: BorderRadius.only( 65 | topLeft: Radius.circular(62), 66 | topRight: Radius.circular(62) 67 | ) 68 | ), 69 | child: Column( 70 | children: [ 71 | TextField( 72 | decoration: InputDecoration( 73 | hintText: 'Username' 74 | ) 75 | ), 76 | 77 | Padding( 78 | padding: EdgeInsets.only(top: 16, bottom: 62), 79 | child: TextField( 80 | decoration: InputDecoration( 81 | hintText: 'Password' 82 | ), 83 | ), 84 | ), 85 | 86 | Container( 87 | height: 45, 88 | width: double.maxFinite, 89 | decoration: BoxDecoration( 90 | color: Colors.deepPurpleAccent, 91 | borderRadius: BorderRadius.all( 92 | Radius.circular(32) 93 | ), 94 | ), 95 | child: Center( 96 | child: Text('LOGIN', 97 | style: TextStyle( 98 | color: Colors.white 99 | ), 100 | ), 101 | ), 102 | ), 103 | Container(height: 8,), 104 | Text("Forgot your Password?", 105 | style: TextStyle( 106 | color: Colors.grey 107 | ), 108 | ), 109 | 110 | Container(height: 70,), 111 | 112 | Row( 113 | mainAxisAlignment: MainAxisAlignment.center, 114 | children: [ 115 | 116 | Container( 117 | width: 60, 118 | height: 60, 119 | decoration: BoxDecoration( 120 | color: Colors.grey[300], 121 | borderRadius: BorderRadius.all( 122 | Radius.circular(100) 123 | ) 124 | ), 125 | child: Center( 126 | child: Icon(Icons.face, 127 | color: Colors.grey[700], 128 | ), 129 | ), 130 | ), 131 | 132 | Container(width: 30,), 133 | 134 | Container( 135 | width: 60, 136 | height: 60, 137 | decoration: BoxDecoration( 138 | color: Colors.grey[300], 139 | borderRadius: BorderRadius.all( 140 | Radius.circular(100) 141 | ) 142 | ), 143 | child: Center( 144 | child: Icon(Icons.fingerprint, 145 | color: Colors.grey[700], 146 | ), 147 | ), 148 | ), 149 | 150 | ], 151 | ) 152 | ], 153 | ), 154 | ), 155 | ) 156 | ], 157 | ), 158 | ), 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /lib/mobile_dashboard.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp( MobileApp()); 5 | 6 | class MobileApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: "Mobile Dashboard", 11 | home: HomePage(), 12 | ); 13 | } 14 | } 15 | 16 | class HomePage extends StatefulWidget { 17 | @override 18 | _HomePageState createState() => _HomePageState(); 19 | } 20 | 21 | class _HomePageState extends State { 22 | 23 | final Color accentColor = Color(0XFFFA2B0F); 24 | 25 | List items = [ 26 | ItemModel("Tasks", 12, 1830), 27 | ItemModel("Analytics", 4, 883), 28 | ItemModel("Works", 2, 326), 29 | ]; 30 | 31 | @override 32 | void initState(){ 33 | super.initState(); 34 | SystemChrome.setEnabledSystemUIOverlays([]); 35 | } 36 | 37 | Widget _buildTitle() { 38 | return Text("Home", 39 | style: TextStyle( 40 | fontSize: 40, 41 | color: Colors.black, 42 | fontWeight: FontWeight.bold 43 | ), 44 | ); 45 | } 46 | 47 | Text _buildText(String title){ 48 | return Text(title, 49 | style: TextStyle( 50 | fontSize: 16, 51 | color: Colors.white, 52 | fontWeight: FontWeight.bold 53 | ), 54 | ); 55 | } 56 | 57 | IconButton _buildButton(IconData icon){ 58 | return IconButton( 59 | onPressed: (){}, 60 | icon: Icon(icon, color: Colors.white,), 61 | ); 62 | } 63 | 64 | Widget _buildBottomCardChildren(){ 65 | return Column( 66 | mainAxisAlignment: MainAxisAlignment.end, 67 | mainAxisSize: MainAxisSize.min, 68 | children: [ 69 | Row( 70 | children: [ 71 | _buildText("All"), 72 | Spacer(), 73 | _buildText("Done") 74 | ], 75 | ), 76 | Container(height: 24,), 77 | Row( 78 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 79 | children: [ 80 | _buildButton(Icons.radio_button_checked), 81 | _buildButton(Icons.home), 82 | _buildButton(Icons.settings), 83 | ], 84 | ) 85 | ], 86 | ); 87 | } 88 | 89 | Widget _buildBottomCard(double width, double height){ 90 | return Container( 91 | width: width, 92 | height: height/3, 93 | padding: EdgeInsets.fromLTRB(16, 0, 16, 16), 94 | decoration: BoxDecoration( 95 | color: accentColor, 96 | borderRadius: BorderRadius.only( 97 | topRight: Radius.circular(16), 98 | topLeft: Radius.circular(16) 99 | ) 100 | ), 101 | child: _buildBottomCardChildren(), 102 | ); 103 | } 104 | 105 | Widget _buildItemCardChild(ItemModel item){ 106 | return Row( 107 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 108 | children: [ 109 | Column( 110 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 111 | children: [ 112 | Text(item.title, 113 | style: TextStyle( 114 | fontSize: 18, 115 | fontWeight: FontWeight.bold 116 | ), 117 | ), 118 | Text(item.numOne.toString(), style: TextStyle( 119 | fontSize: 16, 120 | fontWeight: FontWeight.bold 121 | ), 122 | ) 123 | ], 124 | ), 125 | Column( 126 | mainAxisAlignment: MainAxisAlignment.center, 127 | children: [ 128 | Icon(Icons.pie_chart, color: accentColor,) 129 | ], 130 | ), 131 | Column( 132 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 133 | children: [ 134 | IconButton( 135 | onPressed: () {}, 136 | icon: Icon(Icons.menu, color: Colors.grey,), 137 | ), 138 | 139 | Text(item.numTwo.toString(), style: TextStyle( 140 | fontSize: 16, 141 | fontWeight: FontWeight.bold, 142 | ), 143 | ), 144 | ], 145 | ) 146 | ], 147 | ); 148 | } 149 | 150 | Widget _buildItemCard(ItemModel item){ 151 | return Container( 152 | width: 120, 153 | height: 145, 154 | padding: EdgeInsets.fromLTRB(16, 16, 16, 16), 155 | margin: EdgeInsets.only(left: 32, right: 32, top: 2, bottom: 2), 156 | decoration: BoxDecoration( 157 | color: Colors.white, 158 | borderRadius: BorderRadius.all(Radius.circular(16)), 159 | boxShadow: [ 160 | BoxShadow( 161 | color: Colors.black12, 162 | blurRadius: 1 163 | ) 164 | ] 165 | ), 166 | child: _buildItemCardChild( item), 167 | ); 168 | } 169 | Widget _buildCardsList(){ 170 | return ListView.builder( 171 | itemCount: items.length, 172 | itemBuilder: (context, index){ 173 | var item = items.elementAt(index); 174 | return _buildItemCard( item); 175 | }, 176 | ); 177 | } 178 | 179 | @override 180 | Widget build(BuildContext context) { 181 | final width = MediaQuery.of(context).size.width; 182 | final height = MediaQuery.of(context).size.height; 183 | 184 | return Scaffold( 185 | backgroundColor: Colors.grey[300], 186 | appBar: AppBar( 187 | elevation: 0, 188 | backgroundColor: Colors.grey[300], 189 | title: _buildTitle(), 190 | actions: [ 191 | IconButton( 192 | onPressed: (){}, 193 | icon: Icon(Icons.notifications, 194 | color: Colors.blueGrey, 195 | ), 196 | ) 197 | ], 198 | ), 199 | body: Container( 200 | margin: EdgeInsets.only(top: 16), 201 | child: Stack( 202 | children: [ 203 | Align( 204 | alignment: Alignment.bottomCenter, 205 | child: _buildBottomCard(width, height) 206 | ), 207 | _buildCardsList(), 208 | ], 209 | ), 210 | ), 211 | ); 212 | } 213 | } 214 | 215 | class ItemModel{ 216 | final String title; 217 | final int numOne; 218 | final int numTwo; 219 | 220 | ItemModel(this.title, this.numOne, this.numTwo); 221 | } 222 | 223 | 224 | 225 | -------------------------------------------------------------------------------- /lib/number_picker.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: "Number Picker", 11 | home: HomePage(), 12 | ); 13 | } 14 | } 15 | 16 | class HomePage extends StatelessWidget { 17 | @override 18 | Widget build(BuildContext context) { 19 | return Scaffold( 20 | appBar: AppBar( 21 | title: Text("Number Picker"), 22 | ), 23 | body: Container( 24 | child: Center( 25 | child: MaterialButton( 26 | child: Text("Open Picker"), 27 | onPressed: () => Navigator.of(context).push( 28 | MaterialPageRoute(builder: (c) => PickerPage()), 29 | ), 30 | ), 31 | ), 32 | ), 33 | ); 34 | } 35 | } 36 | 37 | class PickerPage extends StatefulWidget { 38 | @override 39 | _PickerPageState createState() => _PickerPageState(); 40 | } 41 | 42 | class _PickerPageState extends State { 43 | final FixedExtentScrollController scrollController = 44 | new FixedExtentScrollController(initialItem: 1); 45 | 46 | @override 47 | void initState(){ 48 | super.initState(); 49 | 50 | } 51 | 52 | Widget _buildSampleOne(double width, double height){ 53 | return Row( 54 | children: [ 55 | Container( 56 | height: height, 57 | width: width/2, 58 | child: CupertinoPicker.builder( 59 | key: ObjectKey("tt1"), 60 | scrollController: scrollController, 61 | itemExtent: 100, 62 | childCount: 30, 63 | onSelectedItemChanged: (i){}, 64 | itemBuilder: (c, index){ 65 | return Text('${(index+1).toString().padLeft(2, "0")}', 66 | style: TextStyle(color: Colors.deepPurple, fontSize: 80),); 67 | }, 68 | ), 69 | ), 70 | Container( 71 | key: ObjectKey("t3"), 72 | height: height, 73 | width: width/2, 74 | child: CupertinoPicker.builder( 75 | scrollController: scrollController, 76 | itemExtent: 100, 77 | childCount: 30, 78 | backgroundColor: Colors.white, 79 | onSelectedItemChanged: (i){}, 80 | itemBuilder: (c, index){ 81 | return Text(':${(index+1).toString().padLeft(2, "0")}', 82 | style: TextStyle(color: Colors.deepPurple, fontSize: 80),); 83 | }, 84 | ), 85 | ), 86 | ], 87 | ); 88 | } 89 | 90 | @override 91 | Widget build(BuildContext context) { 92 | var height = MediaQuery.of(context).size.height; 93 | var width = MediaQuery.of(context).size.width; 94 | 95 | return Scaffold( 96 | body: _buildSampleOne(width, height), 97 | ); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/profile_challenge.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp(MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: 'Flutter Demo', 10 | theme: ThemeData( 11 | primarySwatch: Colors.blue, 12 | ), 13 | home: MyHomePage(title: 'Flutter Demo Home Page'), 14 | ); 15 | } 16 | } 17 | 18 | class MyHomePage extends StatefulWidget { 19 | MyHomePage({Key key, this.title}) : super(key: key); 20 | 21 | final String title; 22 | 23 | @override 24 | _MyHomePageState createState() => _MyHomePageState(); 25 | } 26 | 27 | class _MyHomePageState extends State { 28 | 29 | final String url = 'https://static.independent.co.uk/s3fs-public/thumbnails/image/2018/09/04/15/lionel-messi-0.jpg?'; 30 | final Color green = Color(0xFF1E8161); 31 | 32 | @override 33 | Widget build(BuildContext context) { 34 | return Scaffold( 35 | appBar: AppBar( 36 | title: Text('Profile'), 37 | elevation: 0, 38 | backgroundColor: green, 39 | leading: IconButton( 40 | icon: Icon(Icons.arrow_back_ios), 41 | onPressed: (){}, 42 | ), 43 | actions: [ 44 | IconButton( 45 | icon: Icon(Icons.search), 46 | onPressed: (){}, 47 | ) 48 | ], 49 | ), 50 | body: Column( 51 | children: [ 52 | Container( 53 | padding: EdgeInsets.only(top: 16), 54 | width: MediaQuery.of(context).size.width, 55 | height: MediaQuery.of(context).size.height/2, 56 | decoration: BoxDecoration( 57 | color: green, 58 | borderRadius: BorderRadius.only( 59 | bottomRight: Radius.circular(32), 60 | bottomLeft: Radius.circular(32) 61 | ), 62 | ), 63 | child: Column( 64 | children: [ 65 | Row( 66 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 67 | children: [ 68 | Padding( 69 | padding: const EdgeInsets.only(left: 16), 70 | child: Column( 71 | children: [ 72 | Text('Familiar', 73 | style: TextStyle( 74 | color: Colors.white 75 | ), 76 | ), 77 | Text('12', 78 | style: TextStyle( 79 | color: Colors.white 80 | ), 81 | ) 82 | ], 83 | ), 84 | ), 85 | Container( 86 | width: 120, 87 | height: 120, 88 | decoration: BoxDecoration( 89 | shape: BoxShape.circle, 90 | image: DecorationImage( 91 | fit: BoxFit.fill, 92 | image: NetworkImage(url) 93 | ) 94 | ), 95 | ), 96 | Padding( 97 | padding: const EdgeInsets.only(right: 16), 98 | child: Column( 99 | children: [ 100 | Text('Following', 101 | style: TextStyle( 102 | color: Colors.white 103 | ), 104 | ), 105 | Text('18', 106 | style: TextStyle( 107 | color: Colors.white 108 | ), 109 | ) 110 | ], 111 | ), 112 | ) 113 | ], 114 | ), 115 | Padding( 116 | padding: const EdgeInsets.only( 117 | top: 10 118 | ), 119 | child: Text("ID: 14552566", 120 | style: TextStyle( 121 | color: Colors.white70 122 | ), 123 | ), 124 | ), 125 | Padding( 126 | padding: const EdgeInsets.only(top: 16, bottom: 32), 127 | child: Text('Herman Jimenez', 128 | style: TextStyle( 129 | color: Colors.white, 130 | fontSize: 24, 131 | fontWeight: FontWeight.bold 132 | ), 133 | ), 134 | ), 135 | Padding( 136 | padding: const EdgeInsets.only(left: 16, right: 16), 137 | child: Row( 138 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 139 | children: [ 140 | Column( 141 | children: [ 142 | Icon(Icons.group_add, color: Colors.white,), 143 | Text('Friends', 144 | style: TextStyle( 145 | color: Colors.white 146 | ), 147 | ), 148 | ], 149 | ), 150 | Column( 151 | children: [ 152 | Icon(Icons.group, color: Colors.white,), 153 | Text('Groups', 154 | style: TextStyle( 155 | color: Colors.white 156 | ), 157 | ), 158 | ], 159 | ), 160 | Column( 161 | children: [ 162 | Icon(Icons.videocam, color: Colors.white,), 163 | Text('Videos', 164 | style: TextStyle( 165 | color: Colors.white 166 | ), 167 | ), 168 | ], 169 | ), 170 | Column( 171 | children: [ 172 | Icon(Icons.favorite, color: Colors.white,), 173 | Text('Likes', 174 | style: TextStyle( 175 | color: Colors.white 176 | ), 177 | ), 178 | ], 179 | ) 180 | ], 181 | ), 182 | ) 183 | ], 184 | ), 185 | ), 186 | Container( 187 | height: MediaQuery.of(context).size.height/3, 188 | padding: EdgeInsets.all(42), 189 | child: Column( 190 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 191 | children: [ 192 | Row( 193 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 194 | children: [ 195 | Column( 196 | children: [ 197 | Icon(Icons.table_chart, color: Colors.grey,), 198 | Text('Leaders', 199 | style: TextStyle( 200 | color: Colors.grey, 201 | fontWeight: FontWeight.bold 202 | ), 203 | ) 204 | ], 205 | ), 206 | Column( 207 | children: [ 208 | Icon(Icons.show_chart, color: Colors.grey,), 209 | Text('Level up', 210 | style: TextStyle( 211 | color: Colors.grey, 212 | fontWeight: FontWeight.bold 213 | ), 214 | ) 215 | ], 216 | ), 217 | Column( 218 | children: [ 219 | Icon(Icons.card_giftcard, color: Colors.grey,), 220 | Text('Leaders', 221 | style: TextStyle( 222 | color: Colors.grey, 223 | fontWeight: FontWeight.bold 224 | ), 225 | ) 226 | ], 227 | ), 228 | ], 229 | ), 230 | Spacer(), 231 | Row( 232 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 233 | children: [ 234 | Column( 235 | children: [ 236 | Icon(Icons.code, color: Colors.grey,), 237 | Text('QR code') 238 | ], 239 | ), 240 | Column( 241 | children: [ 242 | Icon(Icons.blur_circular, color: Colors.grey,), 243 | Text('Daily bonus') 244 | ], 245 | ), 246 | Column( 247 | children: [ 248 | Icon(Icons.visibility, color: Colors.grey,), 249 | Text('Visitors') 250 | ], 251 | ), 252 | ], 253 | ), 254 | ], 255 | ), 256 | ) 257 | ], 258 | ), 259 | ); 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /lib/profile_design.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'dart:math' as math; 4 | 5 | class ProfilePageDesign extends StatefulWidget { 6 | @override 7 | _ProfilePageDesignState createState() => _ProfilePageDesignState(); 8 | } 9 | 10 | class _ProfilePageDesignState extends State { 11 | 12 | @override 13 | void initState() { 14 | super.initState(); 15 | 16 | SystemChrome.setEnabledSystemUIOverlays([]); 17 | } 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | title: "Profile", 23 | home: ProfilePage(), 24 | debugShowCheckedModeBanner: false, 25 | ); 26 | } 27 | } 28 | 29 | class ProfilePage extends StatelessWidget { 30 | 31 | TextStyle _style(){ 32 | return TextStyle( 33 | fontWeight: FontWeight.bold 34 | ); 35 | } 36 | 37 | @override 38 | Widget build(BuildContext context) { 39 | return Scaffold( 40 | appBar: CustomAppBar(), 41 | body: Container( 42 | padding: EdgeInsets.symmetric(horizontal: 16), 43 | child: Column( 44 | crossAxisAlignment: CrossAxisAlignment.start, 45 | children: [ 46 | Text("Name"), 47 | SizedBox(height: 4,), 48 | Text("Milan Short", style: _style(),), 49 | SizedBox(height: 16,), 50 | 51 | Text("Email", style: _style(),), 52 | SizedBox(height: 4,), 53 | Text("milan@gmail.com"), 54 | SizedBox(height: 16,), 55 | 56 | Text("Location", style: _style(),), 57 | SizedBox(height: 4,), 58 | Text("New York, USA"), 59 | SizedBox(height: 16,), 60 | 61 | Text("Language", style: _style(),), 62 | SizedBox(height: 4,), 63 | Text("English, French"), 64 | SizedBox(height: 16,), 65 | 66 | Text("Occupation", style: _style(),), 67 | SizedBox(height: 4,), 68 | Text("Employee"), 69 | SizedBox(height: 16,), 70 | 71 | Divider(color: Colors.grey,) 72 | ], 73 | ), 74 | ), 75 | ); 76 | } 77 | } 78 | 79 | 80 | final String url = "http://chuteirafc.cartacapital.com.br/wp-content/uploads/2018/12/15347041965884.jpg"; 81 | 82 | class CustomAppBar extends StatelessWidget 83 | with PreferredSizeWidget{ 84 | 85 | @override 86 | Size get preferredSize => Size(double.infinity, 320); 87 | 88 | @override 89 | Widget build(BuildContext context) { 90 | return ClipPath( 91 | clipper: MyClipper(), 92 | child: Container( 93 | padding: EdgeInsets.only(top: 4), 94 | decoration: BoxDecoration( 95 | color: Colors.redAccent, 96 | boxShadow: [ 97 | BoxShadow( 98 | color: Colors.red, 99 | blurRadius: 20, 100 | offset: Offset(0, 0) 101 | ) 102 | ] 103 | ), 104 | child: Column( 105 | children: [ 106 | Row( 107 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 108 | children: [ 109 | IconButton( 110 | icon: Icon(Icons.menu, color: Colors.white,), 111 | onPressed: (){}, 112 | ), 113 | 114 | Text("Profile", style: TextStyle( 115 | color: Colors.white, 116 | fontSize: 16, 117 | ),), 118 | 119 | IconButton( 120 | icon: Icon(Icons.notifications, color: Colors.white,), 121 | onPressed: (){}, 122 | ) 123 | ], 124 | ), 125 | 126 | Row( 127 | mainAxisAlignment: MainAxisAlignment.spaceAround, 128 | children: [ 129 | 130 | Column( 131 | children: [ 132 | Container( 133 | width: 100, 134 | height: 100, 135 | decoration: BoxDecoration( 136 | shape: BoxShape.circle, 137 | image: DecorationImage( 138 | fit: BoxFit.cover, 139 | image: NetworkImage(url) 140 | ) 141 | ), 142 | ), 143 | SizedBox(height: 16,), 144 | Text("Milan Short", style: TextStyle( 145 | color: Colors.white, 146 | fontSize: 20 147 | ),) 148 | ], 149 | ), 150 | 151 | Column( 152 | children: [ 153 | Text("Schedule", style: TextStyle( 154 | color: Colors.white 155 | ),), 156 | Text("8", style: TextStyle( 157 | fontSize: 26, 158 | color: Colors.white 159 | ),) 160 | ], 161 | ), 162 | 163 | Column( 164 | children: [ 165 | Text("Events", style: TextStyle( 166 | color: Colors.white 167 | ),), 168 | Text("12", style: TextStyle( 169 | fontSize: 26, 170 | color: Colors.white 171 | ),) 172 | ], 173 | ), 174 | 175 | 176 | Column( 177 | children: [ 178 | Text("Routines", style: TextStyle( 179 | color: Colors.white 180 | ),), 181 | Text("4", style: TextStyle( 182 | fontSize: 26, 183 | color: Colors.white 184 | ),) 185 | ], 186 | ), 187 | ], 188 | ), 189 | Row( 190 | mainAxisAlignment: MainAxisAlignment.end, 191 | children: [ 192 | 193 | Column( 194 | children: [ 195 | Text("Savings", style: TextStyle( 196 | color: Colors.white 197 | ),), 198 | Text("20K", style: TextStyle( 199 | color: Colors.white, 200 | fontSize: 24 201 | ),) 202 | ], 203 | ), 204 | 205 | SizedBox(width: 32,), 206 | 207 | Column( 208 | children: [ 209 | Text("July Goals", 210 | style: TextStyle( 211 | color: Colors.white 212 | ),), 213 | Text("50K", style: TextStyle( 214 | color: Colors.white, 215 | fontSize: 24 216 | )) 217 | ], 218 | ), 219 | 220 | SizedBox(width: 16,) 221 | 222 | ], 223 | ), 224 | SizedBox(height: 8,), 225 | 226 | Align( 227 | alignment: Alignment.bottomRight, 228 | child: GestureDetector( 229 | onTap: (){ 230 | print("//TODO: button clicked"); 231 | }, 232 | child: Padding( 233 | padding: const EdgeInsets.fromLTRB(0, 24, 16, 0), 234 | child: Transform.rotate( 235 | angle: (math.pi * 0.05), 236 | child: Container( 237 | width: 110, 238 | height: 32, 239 | child: Center(child: Text("Edit Profile"),), 240 | decoration: BoxDecoration( 241 | color: Colors.white, 242 | borderRadius: BorderRadius.all(Radius.circular(16)), 243 | boxShadow: [ 244 | BoxShadow( 245 | color: Colors.black12, 246 | blurRadius: 20 247 | ) 248 | ] 249 | ), 250 | ), 251 | ), 252 | ), 253 | ), 254 | ) 255 | ], 256 | ), 257 | ), 258 | ); 259 | } 260 | } 261 | 262 | class MyClipper extends CustomClipper{ 263 | 264 | @override 265 | Path getClip(Size size) { 266 | Path p = Path(); 267 | 268 | p.lineTo(0, size.height-70); 269 | p.lineTo(size.width, size.height); 270 | 271 | p.lineTo(size.width, 0); 272 | 273 | p.close(); 274 | 275 | return p; 276 | } 277 | 278 | @override 279 | bool shouldReclip(CustomClipper oldClipper) { 280 | return true; 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /lib/search_app_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/rendering.dart'; 3 | 4 | void main() => runApp(SearchAppBar()); 5 | 6 | class SearchAppBar extends StatefulWidget { 7 | @override 8 | _SearchAppBarState createState() => new _SearchAppBarState(); 9 | } 10 | 11 | String url = "https://image.iol.co.za/image/1/process/620x349?source=https://cdn.africannewsagency.com/public/ana/media/media/2019/05/15/1557888547382.jpg&operation=CROP&offset=0x41&resize=2999x1679"; 12 | 13 | class _SearchAppBarState extends State { 14 | String appTitle = "AppBar Title"; 15 | 16 | bool isSearchEnabled = true; 17 | 18 | _switchSearchBarState(){ 19 | setState(() { 20 | isSearchEnabled = !isSearchEnabled; 21 | }); 22 | } 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | return new MaterialApp( 27 | title: "My App 2019", 28 | home: Scaffold( 29 | appBar: AppBar( 30 | elevation: 1, 31 | bottomOpacity: 0.5, 32 | title: Text("About"), 33 | ), 34 | body: ClipPath( 35 | clipper: MyClip(), 36 | child: Container( 37 | height: 400, 38 | decoration: BoxDecoration( 39 | image: DecorationImage( 40 | colorFilter: ColorFilter.mode( 41 | Color(0xFF1D5D51), 42 | BlendMode.color, 43 | ), 44 | fit: BoxFit.fitHeight, 45 | image: NetworkImage(url) 46 | ) 47 | ), 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | 55 | class MyClip extends CustomClipper{ 56 | 57 | @override 58 | Path getClip(Size size) { 59 | Path p = Path(); 60 | 61 | p.lineTo(0, size.height); 62 | p.lineTo(size.width, size.height/2); 63 | 64 | p.lineTo(size.width, 0); 65 | 66 | return p; 67 | } 68 | 69 | @override 70 | bool shouldReclip(CustomClipper oldClipper) { 71 | return true; 72 | } 73 | } -------------------------------------------------------------------------------- /lib/sliding_login.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | 4 | void main() => runApp(MyApp()); 5 | 6 | class MyApp extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Sliding Login', 11 | home: HomePage(), 12 | ); 13 | } 14 | } 15 | 16 | class HomePage extends StatefulWidget { 17 | @override 18 | HomePageState createState() { 19 | return HomePageState(); 20 | } 21 | } 22 | 23 | class HomePageState extends State 24 | with SingleTickerProviderStateMixin { 25 | bool isLogin = true; 26 | Animation loginSize; 27 | AnimationController loginController; 28 | AnimatedOpacity opacityAnimation; 29 | Duration animationDuration = Duration(milliseconds: 270); 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | SystemChrome.setEnabledSystemUIOverlays([]); 36 | 37 | loginController = 38 | AnimationController(vsync: this, duration: animationDuration); 39 | 40 | opacityAnimation = 41 | AnimatedOpacity(opacity: 0.0, duration: animationDuration); 42 | } 43 | 44 | @override 45 | void dispose() { 46 | loginController.dispose(); 47 | super.dispose(); 48 | } 49 | 50 | Widget _buildLoginWidgets() { 51 | return Container( 52 | padding: EdgeInsets.only(bottom: 62, top: 16), 53 | width: MediaQuery.of(context).size.width, 54 | height: loginSize.value, 55 | decoration: BoxDecoration( 56 | color: Color(0XFF2a3ed7), 57 | borderRadius: BorderRadius.only( 58 | bottomLeft: Radius.circular(190), 59 | bottomRight: Radius.circular(190))), 60 | child: Align( 61 | alignment: Alignment.bottomCenter, 62 | child: AnimatedOpacity( 63 | opacity: loginController.value, 64 | duration: animationDuration, 65 | child: GestureDetector( 66 | onTap: isLogin ? null : () { 67 | loginController.reverse(); 68 | 69 | setState(() { 70 | isLogin = !isLogin; 71 | }); 72 | }, 73 | child: Container( 74 | child: Text( 75 | 'LOG IN'.toUpperCase(), 76 | style: TextStyle( 77 | fontSize: 32, 78 | fontWeight: FontWeight.bold, 79 | color: Colors.white), 80 | ), 81 | ), 82 | ), 83 | ), 84 | ), 85 | ); 86 | } 87 | 88 | Widget _buildLoginComponents() { 89 | return Column( 90 | mainAxisSize: MainAxisSize.min, 91 | children: [ 92 | Visibility( 93 | visible: isLogin, 94 | child: Padding( 95 | padding: const EdgeInsets.only(left: 42, right: 42), 96 | child: Column( 97 | children: [ 98 | TextField( 99 | style: TextStyle(color: Colors.white, height: 0.5), 100 | decoration: InputDecoration( 101 | prefixIcon: Icon(Icons.email), 102 | hintText: 'Email', 103 | border: OutlineInputBorder( 104 | borderRadius: BorderRadius.all(Radius.circular(32)) 105 | ) 106 | ), 107 | ), 108 | Padding( 109 | padding: const EdgeInsets.only(top: 16), 110 | child: TextField( 111 | style: TextStyle(color: Colors.white, height: 0.5), 112 | decoration: InputDecoration( 113 | prefixIcon: Icon(Icons.vpn_key), 114 | hintText: 'Password', 115 | border: OutlineInputBorder( 116 | borderRadius: BorderRadius.all( 117 | Radius.circular(32)))), 118 | ), 119 | ), 120 | Container( 121 | width: 200, 122 | height: 40, 123 | margin: EdgeInsets.only(top: 32), 124 | decoration: BoxDecoration( 125 | color: Colors.white, 126 | borderRadius: BorderRadius.all(Radius.circular(50)) 127 | ), 128 | child: Center( 129 | child: Text( 130 | 'LOG IN', 131 | style: TextStyle(color: Color(0XFF2a3ed7), 132 | fontWeight: FontWeight.bold 133 | ), 134 | ), 135 | ), 136 | ) 137 | ], 138 | ), 139 | ), 140 | ), 141 | 142 | ], 143 | ); 144 | } 145 | 146 | Widget _buildRegistercomponents() { 147 | return Padding( 148 | padding: EdgeInsets.only( 149 | left: 42, 150 | right: 42, 151 | top: 32, 152 | bottom: 32 153 | ), 154 | child: Column( 155 | mainAxisSize: MainAxisSize.min, 156 | children: [ 157 | Padding( 158 | padding: const EdgeInsets.only(bottom: 32), 159 | child: Text( 160 | 'Sign Up'.toUpperCase(), 161 | style: TextStyle( 162 | fontSize: 32, 163 | fontWeight: FontWeight.bold, 164 | color: Color(0XFF2a3ed7)), 165 | ), 166 | ), 167 | TextField( 168 | style: TextStyle(color: Colors.black, height: 0.5), 169 | decoration: InputDecoration( 170 | prefixIcon: Icon( 171 | Icons.email, 172 | ), 173 | hintText: 'Email', 174 | border: OutlineInputBorder( 175 | borderRadius: BorderRadius.all(Radius.circular(32)))), 176 | ), 177 | Padding( 178 | padding: const EdgeInsets.only(bottom: 16, top: 16), 179 | child: TextField( 180 | style: TextStyle(color: Colors.black, height: 0.5), 181 | decoration: InputDecoration( 182 | prefixIcon: Icon(Icons.vpn_key), 183 | hintText: 'Password', 184 | border: OutlineInputBorder( 185 | borderRadius: BorderRadius.all(Radius.circular(32)))), 186 | ), 187 | ), 188 | TextField( 189 | style: TextStyle(color: Colors.black, height: 0.5), 190 | decoration: InputDecoration( 191 | prefixIcon: Icon(Icons.vpn_key), 192 | hintText: 'Confirm Password', 193 | border: OutlineInputBorder( 194 | borderRadius: BorderRadius.all(Radius.circular(32)))), 195 | ), 196 | Padding( 197 | padding: const EdgeInsets.only(top: 24), 198 | child: Container( 199 | width: 200, 200 | height: 40, 201 | margin: EdgeInsets.only(top: 32), 202 | decoration: BoxDecoration( 203 | color: Color(0XFF2a3ed7), 204 | borderRadius: BorderRadius.all(Radius.circular(50)) 205 | ), 206 | child: Center( 207 | child: Text( 208 | 'SIGN UP', 209 | style: TextStyle(color: Colors.white, 210 | fontWeight: FontWeight.bold 211 | ), 212 | ), 213 | ), 214 | ) , 215 | ) 216 | ], 217 | ), 218 | ); 219 | } 220 | 221 | @override 222 | Widget build(BuildContext context) { 223 | double _defaultLoginSize = MediaQuery.of(context).size.height / 1.6; 224 | 225 | loginSize = Tween(begin: _defaultLoginSize, end: 200).animate( 226 | CurvedAnimation(parent: loginController, curve: Curves.linear)); 227 | 228 | return Scaffold( 229 | backgroundColor: Colors.white, 230 | body: Stack( 231 | children: [ 232 | Align( 233 | alignment: Alignment.bottomCenter, 234 | child: AnimatedOpacity( 235 | opacity: isLogin ? 0.0 : 1.0, 236 | duration: animationDuration, 237 | child: Container(child: _buildRegistercomponents()), 238 | ), 239 | ), 240 | Align( 241 | alignment: Alignment.bottomCenter, 242 | child: Container( 243 | color: isLogin && !loginController.isAnimating ? Colors.white : Colors.transparent, 244 | width: MediaQuery.of(context).size.width, 245 | height: _defaultLoginSize/1.5, 246 | child: Visibility( 247 | visible: isLogin, 248 | child: GestureDetector( 249 | onTap: () { 250 | loginController.forward(); 251 | setState(() { 252 | isLogin = !isLogin; 253 | }); 254 | }, 255 | child: Center( 256 | child: Text( 257 | 'Sign Up'.toUpperCase(), 258 | style: TextStyle( 259 | fontSize: 32, 260 | fontWeight: FontWeight.bold, 261 | color: Color(0XFF2a3ed7), 262 | ), 263 | ), 264 | ), 265 | ), 266 | ), 267 | ), 268 | ), 269 | AnimatedBuilder( 270 | animation: loginController, 271 | builder: (context, child) { 272 | return _buildLoginWidgets(); 273 | }, 274 | ), 275 | Align( 276 | alignment: Alignment.topCenter, 277 | child: Container( 278 | width: MediaQuery.of(context).size.width, 279 | height: MediaQuery.of(context).size.height/2, 280 | child: Center(child: _buildLoginComponents()), 281 | ) 282 | ) 283 | ], 284 | ), 285 | ); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /lib/titled_bottom_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | void main() => runApp( MyApp()); 4 | 5 | class MyApp extends StatelessWidget { 6 | @override 7 | Widget build(BuildContext context) { 8 | return MaterialApp( 9 | title: 'Titled Bar', 10 | home: HomePage(), 11 | ); 12 | } 13 | } 14 | 15 | class HomePage extends StatefulWidget { 16 | @override 17 | State createState() => _HomePageState(); 18 | } 19 | 20 | class _HomePageState extends State { 21 | 22 | final List items = [ 23 | Item('Home', Icons.home), 24 | Item('Search', Icons.search), 25 | Item('Bag', Icons.card_travel), 26 | Item('Orders', Icons.shopping_cart), 27 | Item('Profile', Icons.person_outline), 28 | ]; 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return Scaffold( 33 | appBar: AppBar( 34 | title: Text("Titled Bottom Bar"), 35 | ), 36 | bottomNavigationBar: TitledBottomNavigationBar( 37 | items: items, 38 | ), 39 | ); 40 | } 41 | } 42 | 43 | 44 | class TitledBottomNavigationBar extends StatefulWidget { 45 | final List items; 46 | 47 | const TitledBottomNavigationBar({Key key, this.items}) : super(key: key); 48 | 49 | @override 50 | _TitledBottomNavigationBarState createState() => _TitledBottomNavigationBarState(); 51 | } 52 | 53 | class _TitledBottomNavigationBarState 54 | extends State 55 | with SingleTickerProviderStateMixin{ 56 | 57 | List get items => widget.items; 58 | int selectedIndex = 0; 59 | static const double BAR_HEIGHT = 60; 60 | static const double INDICATOR_HEIGHT = 2; 61 | static const double INDICATOR_WIDTH = 10; 62 | double width = 0; 63 | double indicatorAlignX = 0; 64 | 65 | Duration duration = Duration(milliseconds: 270); 66 | 67 | @override 68 | void initState() { 69 | // select a default item 70 | _select(selectedIndex); 71 | 72 | super.initState(); 73 | } 74 | 75 | @override 76 | Widget build(BuildContext context) { 77 | width = MediaQuery.of(context).size.width; 78 | return Container( 79 | height: BAR_HEIGHT, 80 | width: width, 81 | decoration: BoxDecoration( 82 | color: Colors.white, 83 | boxShadow: [ 84 | BoxShadow( 85 | color: Colors.black12, 86 | blurRadius: 10 87 | ) 88 | ] 89 | ), 90 | child: Stack( 91 | overflow: Overflow.visible, 92 | children: [ 93 | Positioned( 94 | top: INDICATOR_HEIGHT, 95 | child: Row( 96 | crossAxisAlignment: CrossAxisAlignment.end, 97 | children: items.map((item){ 98 | var index = items.indexOf(item); 99 | return GestureDetector( 100 | onTap: ()=> setState((){ 101 | _select(index); 102 | }), 103 | 104 | child: _buildItemWidget(item, index == selectedIndex), 105 | ); 106 | }).toList(), 107 | ), 108 | ), 109 | Positioned( 110 | top: 0, 111 | width: width, 112 | child: AnimatedAlign( 113 | alignment: Alignment(indicatorAlignX, 0), 114 | curve: Curves.linear, 115 | duration: duration, 116 | child: Container( 117 | color: Colors.black, 118 | width: width/items.length, 119 | height: INDICATOR_HEIGHT, 120 | ), 121 | ), 122 | ), 123 | ], 124 | ), 125 | ); 126 | } 127 | 128 | _select(int index) { 129 | selectedIndex = index; 130 | indicatorAlignX = -1 + (2 / (items.length - 1) * index); 131 | } 132 | 133 | Widget _buildItemWidget(Item item, bool isSelected){ 134 | return Container( 135 | color: Colors.white, 136 | height: BAR_HEIGHT, 137 | width: width / items.length, 138 | child: Stack( 139 | alignment: AlignmentDirectional.center, 140 | children: [ 141 | AnimatedOpacity( 142 | opacity: isSelected ? 0.0 : 1.0, 143 | duration: duration, 144 | curve: Curves.linear, 145 | child: Text(item.title), 146 | ), 147 | AnimatedAlign( 148 | duration: duration, 149 | alignment: isSelected ? Alignment.center : Alignment(0, 2.6), 150 | child: Icon(item.icon), 151 | ), 152 | ], 153 | ), 154 | ); 155 | } 156 | } 157 | 158 | class Item{ 159 | final String title; 160 | final IconData icon; 161 | 162 | Item(this.title, this.icon); 163 | } -------------------------------------------------------------------------------- /lib/world_clock.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/cupertino.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:flutter/services.dart'; 7 | 8 | class HomePage extends StatefulWidget { 9 | @override 10 | _HomePageState createState() => _HomePageState(); 11 | } 12 | 13 | final Color bgColor = Colors.white; 14 | 15 | class _HomePageState extends State { 16 | 17 | Stopwatch stopwatch; 18 | double hour = 0; 19 | double minute = 0; 20 | double seconds = 0; 21 | DateTime now = DateTime.now(); 22 | 23 | int currentIndex = 0; 24 | final items = ["Clock", "List", "Settings"]; 25 | final icons = [Icons.alarm, Icons.list, Icons.settings]; 26 | 27 | double _secondPercent() => stopwatch.elapsed.inSeconds / 60; 28 | double _minutesPercent() => minute / 60; 29 | double _hoursPercent() => hour / 24; 30 | 31 | @override 32 | void initState() { 33 | super.initState(); 34 | 35 | SystemChrome.setEnabledSystemUIOverlays([]); 36 | 37 | stopwatch = Stopwatch(); 38 | hour = now.hour.toDouble(); 39 | minute = now.minute.toDouble(); 40 | 41 | Timer.periodic(Duration.zero, (t){ 42 | if(stopwatch.elapsed.inSeconds == 60){ 43 | minute = DateTime.now().minute.toDouble(); 44 | stopwatch.reset(); 45 | }else if(stopwatch.elapsed.inMinutes == 60){ 46 | hour = DateTime.now().second.toDouble(); 47 | stopwatch.reset(); 48 | } 49 | setState(() {}); 50 | }); 51 | 52 | stopwatch.start(); 53 | } 54 | 55 | Widget _addButton(){ 56 | return Container( 57 | height: 50, 58 | width: 50, 59 | margin: EdgeInsets.only(left: 16), 60 | decoration: BoxDecoration( 61 | shape: BoxShape.circle, 62 | color: Colors.redAccent, 63 | boxShadow: [ 64 | BoxShadow( 65 | color: Colors.redAccent.withOpacity(0.5), 66 | blurRadius: 15, 67 | spreadRadius: 2 68 | ) 69 | ] 70 | ), 71 | child: Center( 72 | child: Icon(Icons.add, color: Colors.white, size: 32,), 73 | ), 74 | ); 75 | } 76 | 77 | Widget _editButton(){ 78 | return Container( 79 | height: 50, 80 | width: 50, 81 | margin: EdgeInsets.only(left: 16), 82 | decoration: BoxDecoration( 83 | shape: BoxShape.circle, 84 | color: Colors.white, 85 | boxShadow: [ 86 | BoxShadow( 87 | color: Colors.black12.withOpacity(0.05), 88 | blurRadius: 10, 89 | spreadRadius: 10 90 | ) 91 | ] 92 | ), 93 | child: Center( 94 | child: Icon(Icons.edit, color: Colors.redAccent, size: 32,), 95 | ), 96 | ); 97 | } 98 | 99 | @override 100 | void dispose() { 101 | stopwatch?.stop(); 102 | super.dispose(); 103 | } 104 | 105 | @override 106 | Widget build(BuildContext context) { 107 | return MaterialApp( 108 | home: Scaffold( 109 | backgroundColor: bgColor, 110 | body: Container( 111 | child: Stack( 112 | children: [ 113 | 114 | Positioned( 115 | top: 40, 116 | child: _addButton(), 117 | ), 118 | 119 | Positioned( 120 | top: 40, 121 | right: 16, 122 | child: _editButton(), 123 | ), 124 | 125 | Column( 126 | children: [ 127 | Spacer(), 128 | Spacer(), 129 | Center( 130 | child: Container( 131 | height: 310, 132 | width: 310, 133 | decoration: BoxDecoration( 134 | color: Colors.white, 135 | shape: BoxShape.circle, 136 | boxShadow: [ 137 | BoxShadow( 138 | color: Colors.black26.withOpacity(0.04), 139 | blurRadius: 10, 140 | offset: Offset(-12, 0), 141 | spreadRadius: 2 142 | ), 143 | BoxShadow( 144 | color: Colors.black26.withOpacity(0.04), 145 | blurRadius: 10, 146 | offset: Offset(12, 0), 147 | spreadRadius: 5 148 | ), 149 | ] 150 | ), 151 | child: Padding( 152 | padding: const EdgeInsets.all(8.0), 153 | child: CustomPaint( 154 | painter: LinesPainter(), 155 | child: Container( 156 | margin: const EdgeInsets.all(32.0), 157 | decoration: BoxDecoration( 158 | color: bgColor, 159 | shape: BoxShape.circle, 160 | boxShadow: [ 161 | BoxShadow( 162 | color: Colors.black26.withOpacity(0.03), 163 | blurRadius: 5, 164 | spreadRadius: 8 165 | ), 166 | ] 167 | ), 168 | child: CustomPaint( 169 | painter: TimeLinesPainter( 170 | lineType: LineType.minute, 171 | tick: _minutesPercent() 172 | ), 173 | child: CustomPaint( 174 | painter: TimeLinesPainter( 175 | lineType: LineType.hour, 176 | tick: _hoursPercent() 177 | ), 178 | child: CustomPaint( 179 | painter: TimeLinesPainter( 180 | lineType: LineType.second, 181 | tick: _secondPercent() 182 | ) 183 | ), 184 | ), 185 | ), 186 | ), 187 | ), 188 | ), 189 | ), 190 | ), 191 | 192 | SizedBox(height: 40,), 193 | Text("Luanda", style: TextStyle( 194 | color: Colors.redAccent, 195 | fontSize: 32, 196 | ),), 197 | Text("${hour.round()}:${minute.round()} ${TimeOfDay.fromDateTime(now).period == DayPeriod.am ? 'AM' : 'PM'}", style: TextStyle( 198 | color: Colors.black, 199 | fontSize: 50, 200 | )), 201 | Spacer() 202 | ], 203 | ), 204 | 205 | ], 206 | ), 207 | ), 208 | bottomNavigationBar: Builder( 209 | builder: (context){ 210 | 211 | return Container( 212 | height: 70, 213 | width: MediaQuery.of(context).size.width, 214 | child: Row( 215 | mainAxisAlignment: MainAxisAlignment.spaceAround, 216 | children: items.map((t){ 217 | return _getItem(t, items.indexOf(t)); 218 | }).toList(), 219 | ), 220 | ); 221 | }, 222 | ), 223 | ), 224 | ); 225 | } 226 | 227 | Widget _getItem(String t, int index) { 228 | final selected = index == currentIndex; 229 | final color = selected ? Colors.black : Colors.grey; 230 | 231 | return GestureDetector( 232 | onTap: (){ 233 | setState(() { 234 | currentIndex = index; 235 | }); 236 | }, 237 | child: Column( 238 | children: [ 239 | Icon(icons.elementAt(index), size: selected ? 40 : 32, color: color,), 240 | Text(t, style: TextStyle( 241 | color: color 242 | ),) 243 | ], 244 | ), 245 | ); 246 | } 247 | } 248 | 249 | enum LineType{ hour, minute, second } 250 | 251 | class LinesPainter extends CustomPainter{ 252 | 253 | final Paint linePainter; 254 | 255 | final double lineHeight = 8; 256 | final int maxLines = 30; 257 | 258 | LinesPainter(): 259 | linePainter = Paint() 260 | ..color = Colors.redAccent 261 | ..style = PaintingStyle.stroke 262 | ..strokeWidth = 1.5; 263 | 264 | @override 265 | void paint(Canvas canvas, Size size) { 266 | canvas.translate(size.width/2, size.height/2); 267 | 268 | canvas.save(); 269 | 270 | final radius = size.width/2; 271 | 272 | List.generate(maxLines, (i){ 273 | canvas.drawLine( 274 | Offset(0, radius), 275 | Offset(0, radius - 8), 276 | linePainter 277 | ); 278 | canvas.rotate(2 * pi / maxLines); 279 | }); 280 | 281 | canvas.restore(); 282 | } 283 | 284 | @override 285 | bool shouldRepaint(CustomPainter oldDelegate) => true; 286 | } 287 | 288 | class TimeLinesPainter extends CustomPainter{ 289 | 290 | final Paint linePainter; 291 | final Paint hourPainter; 292 | final Paint minutePainter; 293 | final double tick; 294 | final LineType lineType; 295 | 296 | TimeLinesPainter({this.tick, this.lineType}): 297 | linePainter = Paint() 298 | ..color = Colors.redAccent 299 | ..style = PaintingStyle.stroke 300 | ..strokeWidth = 2.5, 301 | minutePainter = Paint() 302 | ..color = Colors.black38 303 | ..style = PaintingStyle.stroke 304 | ..strokeWidth = 3.5, 305 | hourPainter = Paint() 306 | ..color = Colors.black 307 | ..style = PaintingStyle.stroke 308 | ..strokeWidth = 4.5; 309 | 310 | @override 311 | void paint(Canvas canvas, Size size) { 312 | final radius = size.width / 2; 313 | 314 | canvas.translate(radius, radius); 315 | 316 | switch(lineType){ 317 | case LineType.hour: 318 | canvas.rotate(24 * pi * tick ); 319 | canvas.drawPath(_hourPath(radius), hourPainter); 320 | break; 321 | case LineType.minute: 322 | canvas.rotate(2 * pi * tick ); 323 | canvas.drawPath(_minutePath(radius), minutePainter); 324 | break; 325 | case LineType.second: 326 | canvas.rotate(2 * pi * tick ); 327 | canvas.drawPath(_secondPath(radius), linePainter); 328 | canvas.drawShadow(_secondPath(radius), Colors.black26, 100, true); 329 | 330 | break; 331 | } 332 | } 333 | 334 | Path _hourPath(double radius){ 335 | return Path() 336 | ..lineTo(0, -((radius/1.4)/2)) 337 | ..close(); 338 | } 339 | 340 | Path _minutePath(double radius){ 341 | return Path() 342 | ..lineTo(0, -(radius/1.4)) 343 | ..close(); 344 | } 345 | 346 | Path _secondPath(double radius){ 347 | return Path() 348 | ..lineTo(0, -(radius+10)) 349 | ..close(); 350 | } 351 | 352 | @override 353 | bool shouldRepaint(CustomPainter oldDelegate) => true; 354 | } -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | 9 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 10 | } 11 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = my_flutter_challenges 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.pedromassango.myFlutterChallenges 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2020 com.pedromassango. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_challenges 2 | description: A new Flutter project containing all my flutter UI challenges 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # Read more about versioning at semver.org. 10 | version: 1.0.0+1 11 | 12 | environment: 13 | sdk: ">=2.13.0 <3.0.0" 14 | 15 | dependencies: 16 | flutter: 17 | sdk: flutter 18 | 19 | # The following adds the Cupertino Icons font to your application. 20 | # Use with the CupertinoIcons class for iOS style icons. 21 | cupertino_icons: ^0.1.2 22 | bottom_navy_bar: ^2.2.0 23 | fl_chart: ^0.36.2 24 | 25 | dev_dependencies: 26 | flutter_test: 27 | sdk: flutter 28 | 29 | 30 | # For information on the generic Dart part of this file, see the 31 | # following page: https://www.dartlang.org/tools/pub/pubspec 32 | 33 | # The following section is specific to Flutter. 34 | flutter: 35 | 36 | # The following line ensures that the Material Icons font is 37 | # included with your application, so that you can use the icons in 38 | # the material Icons class. 39 | uses-material-design: true 40 | 41 | assets: 42 | - images/martian_surface.png 43 | # To add assets to your application, add an assets section, like this: 44 | # assets: 45 | # - images/a_dot_burr.jpeg 46 | # - images/a_dot_ham.jpeg 47 | 48 | # An image asset can refer to one or more resolution-specific "variants", see 49 | # https://flutter.io/assets-and-images/#resolution-aware. 50 | 51 | # For details regarding adding assets from package dependencies, see 52 | # https://flutter.io/assets-and-images/#from-packages 53 | 54 | # To add custom fonts to your application, add a fonts section here, 55 | # in this "flutter" section. Each entry in this list should have a 56 | # "family" key with the font family name, and a "fonts" key with a 57 | # list giving the asset and other descriptors for the font. For 58 | # example: 59 | # fonts: 60 | # - family: Schyler 61 | # fonts: 62 | # - asset: fonts/Schyler-Regular.ttf 63 | # - asset: fonts/Schyler-Italic.ttf 64 | # style: italic 65 | # - family: Trajan Pro 66 | # fonts: 67 | # - asset: fonts/TrajanPro.ttf 68 | # - asset: fonts/TrajanPro_Bold.ttf 69 | # weight: 700 70 | # 71 | # For details regarding fonts from package dependencies, 72 | # see https://flutter.io/custom-fonts/#from-packages 73 | -------------------------------------------------------------------------------- /screenshots/bank_app_ui.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/bank_app_ui.gif -------------------------------------------------------------------------------- /screenshots/coffee_app_auth_page.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/coffee_app_auth_page.gif -------------------------------------------------------------------------------- /screenshots/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/dashboard.png -------------------------------------------------------------------------------- /screenshots/delivery.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/delivery.gif -------------------------------------------------------------------------------- /screenshots/delivery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/delivery.png -------------------------------------------------------------------------------- /screenshots/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/home.png -------------------------------------------------------------------------------- /screenshots/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/login.png -------------------------------------------------------------------------------- /screenshots/navy2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/navy2.gif -------------------------------------------------------------------------------- /screenshots/options_menu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/options_menu.gif -------------------------------------------------------------------------------- /screenshots/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/profile.png -------------------------------------------------------------------------------- /screenshots/profile_design.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/profile_design.png -------------------------------------------------------------------------------- /screenshots/sliding_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/sliding_login.png -------------------------------------------------------------------------------- /screenshots/slidl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/slidl.gif -------------------------------------------------------------------------------- /screenshots/sushi_ui.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/sushi_ui.gif -------------------------------------------------------------------------------- /screenshots/ticket_booking.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/ticket_booking.gif -------------------------------------------------------------------------------- /screenshots/titled_bottom_bar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/titled_bottom_bar.gif -------------------------------------------------------------------------------- /screenshots/world_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pedromassango/my_flutter_challenges/8fc72d096569907746838676fe6a649134f8edf5/screenshots/world_clock.png -------------------------------------------------------------------------------- /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_challenges/profile_challenge.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 | --------------------------------------------------------------------------------