├── .gitignore ├── .metadata ├── LICENSE.md ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── thealteria │ │ │ │ └── getx_start_project │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── 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 │ │ │ └── styles.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets └── images │ └── ic_gallery.png ├── fonts ├── Nunito-Bold.ttf ├── Nunito-Regular.ttf └── Nunito-SemiBold.ttf ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app │ ├── common │ │ ├── constants.dart │ │ ├── storage │ │ │ └── storage.dart │ │ ├── util │ │ │ ├── exports.dart │ │ │ ├── extensions.dart │ │ │ ├── initializer.dart │ │ │ ├── loading_dialog.dart │ │ │ ├── utils.dart │ │ │ └── validators.dart │ │ └── values │ │ │ ├── app_colors.dart │ │ │ ├── app_images.dart │ │ │ ├── strings.dart │ │ │ └── styles │ │ │ ├── app_text_style.dart │ │ │ ├── dimens.dart │ │ │ └── theme.dart │ ├── data │ │ ├── api_helper.dart │ │ ├── api_helper_impl.dart │ │ ├── api_response.dart │ │ ├── errors │ │ │ └── api_error.dart │ │ └── interface_controller │ │ │ └── api_interface_controller.dart │ ├── modules │ │ ├── home │ │ │ ├── bindings │ │ │ │ └── home_binding.dart │ │ │ ├── controllers │ │ │ │ └── home_controller.dart │ │ │ └── views │ │ │ │ └── home_view.dart │ │ └── widgets │ │ │ ├── base_widget.dart │ │ │ ├── custom_appbar_widget.dart │ │ │ ├── custom_back_button.dart │ │ │ ├── custom_card_widget.dart │ │ │ ├── custom_checkbox_widget.dart │ │ │ ├── custom_drawer_header.dart │ │ │ ├── custom_drawer_widget.dart │ │ │ ├── custom_dropdown_textfield.dart │ │ │ ├── custom_elevated_button.dart │ │ │ ├── custom_error_widget.dart │ │ │ ├── custom_image_widget.dart │ │ │ ├── custom_inkwell_widget.dart │ │ │ ├── custom_listtile_widget.dart │ │ │ ├── custom_on_board_card_widget.dart │ │ │ ├── custom_password_field.dart │ │ │ ├── custom_retry_widget.dart │ │ │ ├── custom_rich_text_widget.dart │ │ │ ├── custom_row_text_widget.dart │ │ │ ├── custom_text_button.dart │ │ │ ├── custom_text_field_widget.dart │ │ │ ├── on_boarding_base_widget.dart │ │ │ └── stroke_background.dart │ └── routes │ │ ├── app_pages.dart │ │ └── app_routes.dart └── main.dart └── pubspec.yaml /.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 | # Vscode related 20 | .classpath 21 | .project 22 | .settings/ 23 | .vscode/ 24 | *.code-workspace 25 | .history/ 26 | 27 | # Flutter repo-specific 28 | /bin/cache/ 29 | /bin/mingit/ 30 | /dev/benchmarks/mega_gallery/ 31 | /dev/bots/.recipe_deps 32 | /dev/bots/android_tools/ 33 | /dev/docs/doc/ 34 | /dev/docs/flutter.docs.zip 35 | /dev/docs/lib/ 36 | /dev/docs/pubspec.yaml 37 | /dev/integration_tests/**/xcuserdata 38 | /dev/integration_tests/**/Pods 39 | /packages/flutter/coverage/ 40 | version 41 | 42 | # packages file containing multi-root paths 43 | .packages.generated 44 | 45 | # Flutter/Dart/Pub related 46 | **/doc/api/ 47 | **/ios/Flutter/.last_build_id 48 | .dart_tool/ 49 | .flutter-plugins 50 | .flutter-plugins-dependencies 51 | .packages 52 | .pub-cache/ 53 | .pub/ 54 | /build/ 55 | flutter_*.png 56 | linked_*.ds 57 | unlinked.ds 58 | unlinked_spec.ds 59 | 60 | # Web related 61 | lib/generated_plugin_registrant.dart 62 | 63 | # Symbolication related 64 | app.*.symbols 65 | 66 | # Obfuscation related 67 | app.*.map.json 68 | 69 | # Android related 70 | **/android/**/gradle-wrapper.jar 71 | **/android/.gradle 72 | **/android/captures/ 73 | **/android/gradlew 74 | **/android/gradlew.bat 75 | **/android/local.properties 76 | **/android/**/GeneratedPluginRegistrant.java 77 | **/android/key.properties 78 | *.jks 79 | 80 | # iOS/XCode related 81 | **/ios/**/*.mode1v3 82 | **/ios/**/*.mode2v3 83 | **/ios/**/*.moved-aside 84 | **/ios/**/*.pbxuser 85 | **/ios/**/*.perspectivev3 86 | **/ios/**/*sync/ 87 | **/ios/**/.sconsign.dblite 88 | **/ios/**/.tags* 89 | **/ios/**/.vagrant/ 90 | **/ios/**/DerivedData/ 91 | **/ios/**/Icon? 92 | **/ios/**/Pods/ 93 | **/ios/**/.symlinks/ 94 | **/ios/**/profile 95 | **/ios/**/xcuserdata 96 | **/ios/.generated/ 97 | **/ios/Flutter/App.framework 98 | **/ios/Flutter/Flutter.framework 99 | **/ios/Flutter/Flutter.podspec 100 | **/ios/Flutter/Generated.xcconfig 101 | **/ios/Flutter/app.flx 102 | **/ios/Flutter/app.zip 103 | **/ios/Flutter/flutter_assets/ 104 | **/ios/Flutter/flutter_export_environment.sh 105 | **/ios/ServiceDefinitions.json 106 | **/ios/Runner/GeneratedPluginRegistrant.* 107 | 108 | # macOS 109 | **/macos/Flutter/GeneratedPluginRegistrant.swift 110 | **/macos/Flutter/Flutter-Debug.xcconfig 111 | **/macos/Flutter/Flutter-Release.xcconfig 112 | **/macos/Flutter/Flutter-Profile.xcconfig 113 | 114 | # Coverage 115 | coverage/ 116 | 117 | # Exceptions to above rules. 118 | !**/ios/**/default.mode1v3 119 | !**/ios/**/default.mode2v3 120 | !**/ios/**/default.pbxuser 121 | !**/ios/**/default.perspectivev3 122 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 123 | !/dev/ci/**/Gemfile.lock 124 | -------------------------------------------------------------------------------- /.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: 78910062997c3a836feee883712c241a5fd22983 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Aman Gupta 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GetX Boilerplate Template 2 | 3 | A boilerplate project created in flutter using GetX. 4 | 5 | ## Getting Started 6 | 7 | The boilerplate contains the minimal implementation required to create a new library or project. The repository code is preloaded with some basic components and utilities like basic app architecture, initializer, app theme, linting, constants, **api error handling** with proper errors display using `GetConnect` along with a `**retry button**` and storage using `get_storage`. Some 3rd party dependencies required to create a new project as per your preference. By using boilerplate code as standard initializer, we can have same patterns in all the projects that will inherit it if you're using GetX. This will also help in reducing setup & development time by allowing you to use same code pattern and avoid re-writing from scratch. 8 | 9 | ## How to Use 10 | 11 | **Step 1:** 12 | 13 | Download or clone this repo by using the link below: 14 | 15 | ``` 16 | https://github.com/thealteria/flutter_getx_template.git 17 | ``` 18 | 19 | Or simply click on the **Use this template** button and make your own repository using this template. 20 | 21 | **Step 2:** 22 | 23 | Go to project root and execute the following command in console to get the required dependencies: 24 | 25 | ``` 26 | flutter pub get 27 | ``` 28 | 29 | **NOTE**: Don't forget to change the 'app name' and 'package name' in android, ios, pubspec and strings files. 30 | 31 | ## Boilerplate Features: 32 | 33 | * Initializer - to intialize dependencies on startup 34 | * Home 35 | * Routing 36 | * Theme 37 | * Dynamic UI support 38 | * GetConnect with custom retry button and error handling 39 | * GetStorage 40 | * GetX (State Management and Naviagtion) 41 | * Custom Validations, widgets, dialogs, extensions and much more 42 | 43 | ### Libraries & Tools Used 44 | 45 | * [GetX](https://github.com/jonataslaw/getx) 46 | * [Storage](https://github.com/jonataslaw/get_storage) 47 | * [ScreenUtil](https://github.com/OpenFlutter/flutter_screenutil/) 48 | * [ImagePicker](https://github.com/flutter/plugins) 49 | * [ImageCropper](https://github.com/hnvn/flutter_image_cropper) 50 | * [ImagePicker](https://github.com/flutter/plugins) 51 | * [Intl](https://github.com/dart-lang/intl) 52 | * [OctoImage](https://github.com/Baseflow/octo_image) 53 | 54 | ### Folder Structure 55 | Here is the core folder structure which flutter provides. 56 | 57 | ``` 58 | flutter-app/ 59 | |- android 60 | |- build 61 | |- ios 62 | |- lib 63 | |- test 64 | ``` 65 | 66 | Here is the folder structure we have been using in this project 67 | 68 | ``` 69 | lib/ 70 | |- app/ 71 | |- main.dart 72 | ``` 73 | 74 | ``` 75 | app/ 76 | |- common/ 77 | |- storage/ 78 | |- util/ 79 | |- values/ 80 | |- constants.dart 81 | |- data/ 82 | |- errors/ 83 | |- interface_controller/ 84 | |- api_helper.dart 85 | |- app_response.dart 86 | |- modules/ 87 | |- home/ 88 | |- widgets/ 89 | |- routes/ 90 | ``` 91 | 92 | Now, lets dive into the lib folder which has the main code for the application. 93 | 94 | ``` 95 | 1- common - Contains all the utilities/common functions which are using throughout the app. This directory contains `constants`. `utilities`, `theme`, `strings`, `dimensions`, `storage`, `text styles`, `colors` and `images path`. 96 | 2- data - Contains the data layer of your project, includes a controller for retry apis, `custom errors` and response & error handling. 97 | 3- modules - Contains all the ui of your project, contains sub directory for each screen and custo widgets as per the need. 98 | 4- routes - Contains the files for routes for your application. 99 | 5- main.dart - This is the starting point of the application. All the application level configurations are defined in this file i.e, theme, routes, title, orientation etc. 100 | ``` 101 | **NOTE**: You can use [Get Cli](https://github.com/jonataslaw/get_cli) to auto generate ui pages, controllers and routes. 102 | 103 | ## Conclusion 104 | 105 | This boilerplate template maybe seen over-architectured for what it is - but it is an example only. You can always customize it as per your preferences and need. All the issues/pull requests are welcome to make this boilerplate project more easy-to-use. If you liked it then don’t forget to ⭐ the repo to show your support🙂 106 | 107 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | analyzer: 13 | # strong-mode: 14 | # Will become the default once non-nullable types land 15 | # https://github.com/dart-lang/sdk/issues/31410#issuecomment-510683629 16 | # implicit-casts: false 17 | 18 | errors: 19 | missing_required_param: warning 20 | unnecessary_this: ignore 21 | 22 | constant_identifier_names: ignore 23 | 24 | linter: 25 | # The lint rules applied to this project can be customized in the 26 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 27 | # included above or to enable additional rules. A list of all available lints 28 | # and their documentation is published at 29 | # https://dart-lang.github.io/linter/lints/index.html. 30 | # 31 | # Instead of disabling a lint rule for the entire project in the 32 | # section below, it can also be suppressed for a single line of code 33 | # or a specific dart file by using the `// ignore: name_of_lint` and 34 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 35 | # producing the lint. 36 | rules: 37 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 38 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 39 | # Additional information about this file can be found at 40 | # https://dart.dev/guides/language/analysis-options 41 | -------------------------------------------------------------------------------- /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 31 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.thealteria.flutter_getx_template" 42 | minSdkVersion 16 43 | targetSdkVersion 31 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | } 64 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 20 | 24 | 28 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/thealteria/getx_start_project/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.thealteria.flutter_getx_template 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /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.6.20' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.2.2' 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 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | android.enableR8=true 5 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/images/ic_gallery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/assets/images/ic_gallery.png -------------------------------------------------------------------------------- /fonts/Nunito-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/fonts/Nunito-Bold.ttf -------------------------------------------------------------------------------- /fonts/Nunito-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/fonts/Nunito-Regular.ttf -------------------------------------------------------------------------------- /fonts/Nunito-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/fonts/Nunito-SemiBold.ttf -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/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 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 13 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 14 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 15 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | ); 26 | name = "Embed Frameworks"; 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 33 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 34 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 35 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 36 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 38 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 39 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 40 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9740EEB11CF90186004384FC /* Flutter */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 62 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 63 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 64 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 65 | ); 66 | name = Flutter; 67 | sourceTree = ""; 68 | }; 69 | 97C146E51CF9000F007C117D = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9740EEB11CF90186004384FC /* Flutter */, 73 | 97C146F01CF9000F007C117D /* Runner */, 74 | 97C146EF1CF9000F007C117D /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 97C146EF1CF9000F007C117D /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 97C146EE1CF9000F007C117D /* Runner.app */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 97C146F01CF9000F007C117D /* Runner */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 90 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 91 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 92 | 97C147021CF9000F007C117D /* Info.plist */, 93 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 94 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 95 | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, 96 | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, 97 | ); 98 | path = Runner; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 97C146ED1CF9000F007C117D /* Runner */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 107 | buildPhases = ( 108 | 9740EEB61CF901F6004384FC /* Run Script */, 109 | 97C146EA1CF9000F007C117D /* Sources */, 110 | 97C146EB1CF9000F007C117D /* Frameworks */, 111 | 97C146EC1CF9000F007C117D /* Resources */, 112 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 113 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 114 | ); 115 | buildRules = ( 116 | ); 117 | dependencies = ( 118 | ); 119 | name = Runner; 120 | productName = Runner; 121 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 122 | productType = "com.apple.product-type.application"; 123 | }; 124 | /* End PBXNativeTarget section */ 125 | 126 | /* Begin PBXProject section */ 127 | 97C146E61CF9000F007C117D /* Project object */ = { 128 | isa = PBXProject; 129 | attributes = { 130 | LastUpgradeCheck = 1020; 131 | ORGANIZATIONNAME = ""; 132 | TargetAttributes = { 133 | 97C146ED1CF9000F007C117D = { 134 | CreatedOnToolsVersion = 7.3.1; 135 | LastSwiftMigration = 1100; 136 | }; 137 | }; 138 | }; 139 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 140 | compatibilityVersion = "Xcode 9.3"; 141 | developmentRegion = en; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | Base, 146 | ); 147 | mainGroup = 97C146E51CF9000F007C117D; 148 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 149 | projectDirPath = ""; 150 | projectRoot = ""; 151 | targets = ( 152 | 97C146ED1CF9000F007C117D /* Runner */, 153 | ); 154 | }; 155 | /* End PBXProject section */ 156 | 157 | /* Begin PBXResourcesBuildPhase section */ 158 | 97C146EC1CF9000F007C117D /* Resources */ = { 159 | isa = PBXResourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 163 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 164 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 165 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 166 | ); 167 | runOnlyForDeploymentPostprocessing = 0; 168 | }; 169 | /* End PBXResourcesBuildPhase section */ 170 | 171 | /* Begin PBXShellScriptBuildPhase section */ 172 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 173 | isa = PBXShellScriptBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | inputPaths = ( 178 | ); 179 | name = "Thin Binary"; 180 | outputPaths = ( 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | shellPath = /bin/sh; 184 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; 185 | }; 186 | 9740EEB61CF901F6004384FC /* Run Script */ = { 187 | isa = PBXShellScriptBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | ); 191 | inputPaths = ( 192 | ); 193 | name = "Run Script"; 194 | outputPaths = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | shellPath = /bin/sh; 198 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; 199 | }; 200 | /* End PBXShellScriptBuildPhase section */ 201 | 202 | /* Begin PBXSourcesBuildPhase section */ 203 | 97C146EA1CF9000F007C117D /* Sources */ = { 204 | isa = PBXSourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 208 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXSourcesBuildPhase section */ 213 | 214 | /* Begin PBXVariantGroup section */ 215 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 216 | isa = PBXVariantGroup; 217 | children = ( 218 | 97C146FB1CF9000F007C117D /* Base */, 219 | ); 220 | name = Main.storyboard; 221 | sourceTree = ""; 222 | }; 223 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 224 | isa = PBXVariantGroup; 225 | children = ( 226 | 97C147001CF9000F007C117D /* Base */, 227 | ); 228 | name = LaunchScreen.storyboard; 229 | sourceTree = ""; 230 | }; 231 | /* End PBXVariantGroup section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 249021D3217E4FDB00AE95B9 /* Profile */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 244 | CLANG_WARN_BOOL_CONVERSION = YES; 245 | CLANG_WARN_COMMA = YES; 246 | CLANG_WARN_CONSTANT_CONVERSION = YES; 247 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SUPPORTED_PLATFORMS = iphoneos; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Profile; 283 | }; 284 | 249021D4217E4FDB00AE95B9 /* Profile */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CLANG_ENABLE_MODULES = YES; 290 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 291 | ENABLE_BITCODE = NO; 292 | FRAMEWORK_SEARCH_PATHS = ( 293 | "$(inherited)", 294 | "$(PROJECT_DIR)/Flutter", 295 | ); 296 | INFOPLIST_FILE = Runner/Info.plist; 297 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 298 | LIBRARY_SEARCH_PATHS = ( 299 | "$(inherited)", 300 | "$(PROJECT_DIR)/Flutter", 301 | ); 302 | PRODUCT_BUNDLE_IDENTIFIER = com.thealteria.getxStartProject; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 305 | SWIFT_VERSION = 5.0; 306 | VERSIONING_SYSTEM = "apple-generic"; 307 | }; 308 | name = Profile; 309 | }; 310 | 97C147031CF9000F007C117D /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_COMMA = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 330 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 331 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 334 | CLANG_WARN_STRICT_PROTOTYPES = YES; 335 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 336 | CLANG_WARN_UNREACHABLE_CODE = YES; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 339 | COPY_PHASE_STRIP = NO; 340 | DEBUG_INFORMATION_FORMAT = dwarf; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | ENABLE_TESTABILITY = YES; 343 | GCC_C_LANGUAGE_STANDARD = gnu99; 344 | GCC_DYNAMIC_NO_PIC = NO; 345 | GCC_NO_COMMON_BLOCKS = YES; 346 | GCC_OPTIMIZATION_LEVEL = 0; 347 | GCC_PREPROCESSOR_DEFINITIONS = ( 348 | "DEBUG=1", 349 | "$(inherited)", 350 | ); 351 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 353 | GCC_WARN_UNDECLARED_SELECTOR = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 355 | GCC_WARN_UNUSED_FUNCTION = YES; 356 | GCC_WARN_UNUSED_VARIABLE = YES; 357 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 358 | MTL_ENABLE_DEBUG_INFO = YES; 359 | ONLY_ACTIVE_ARCH = YES; 360 | SDKROOT = iphoneos; 361 | TARGETED_DEVICE_FAMILY = "1,2"; 362 | }; 363 | name = Debug; 364 | }; 365 | 97C147041CF9000F007C117D /* Release */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_ANALYZER_NONNULL = YES; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_COMMA = YES; 377 | CLANG_WARN_CONSTANT_CONVERSION = YES; 378 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 379 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 380 | CLANG_WARN_EMPTY_BODY = YES; 381 | CLANG_WARN_ENUM_CONVERSION = YES; 382 | CLANG_WARN_INFINITE_RECURSION = YES; 383 | CLANG_WARN_INT_CONVERSION = YES; 384 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 385 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 386 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 387 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 388 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 389 | CLANG_WARN_STRICT_PROTOTYPES = YES; 390 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 391 | CLANG_WARN_UNREACHABLE_CODE = YES; 392 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 393 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 394 | COPY_PHASE_STRIP = NO; 395 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 396 | ENABLE_NS_ASSERTIONS = NO; 397 | ENABLE_STRICT_OBJC_MSGSEND = YES; 398 | GCC_C_LANGUAGE_STANDARD = gnu99; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 402 | GCC_WARN_UNDECLARED_SELECTOR = YES; 403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 404 | GCC_WARN_UNUSED_FUNCTION = YES; 405 | GCC_WARN_UNUSED_VARIABLE = YES; 406 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 407 | MTL_ENABLE_DEBUG_INFO = NO; 408 | SDKROOT = iphoneos; 409 | SUPPORTED_PLATFORMS = iphoneos; 410 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 411 | TARGETED_DEVICE_FAMILY = "1,2"; 412 | VALIDATE_PRODUCT = YES; 413 | }; 414 | name = Release; 415 | }; 416 | 97C147061CF9000F007C117D /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 419 | buildSettings = { 420 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 421 | CLANG_ENABLE_MODULES = YES; 422 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 423 | ENABLE_BITCODE = NO; 424 | FRAMEWORK_SEARCH_PATHS = ( 425 | "$(inherited)", 426 | "$(PROJECT_DIR)/Flutter", 427 | ); 428 | INFOPLIST_FILE = Runner/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 430 | LIBRARY_SEARCH_PATHS = ( 431 | "$(inherited)", 432 | "$(PROJECT_DIR)/Flutter", 433 | ); 434 | PRODUCT_BUNDLE_IDENTIFIER = com.thealteria.getxStartProject; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 437 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 438 | SWIFT_VERSION = 5.0; 439 | VERSIONING_SYSTEM = "apple-generic"; 440 | }; 441 | name = Debug; 442 | }; 443 | 97C147071CF9000F007C117D /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 446 | buildSettings = { 447 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 448 | CLANG_ENABLE_MODULES = YES; 449 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; 450 | ENABLE_BITCODE = NO; 451 | FRAMEWORK_SEARCH_PATHS = ( 452 | "$(inherited)", 453 | "$(PROJECT_DIR)/Flutter", 454 | ); 455 | INFOPLIST_FILE = Runner/Info.plist; 456 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 457 | LIBRARY_SEARCH_PATHS = ( 458 | "$(inherited)", 459 | "$(PROJECT_DIR)/Flutter", 460 | ); 461 | PRODUCT_BUNDLE_IDENTIFIER = com.thealteria.getxStartProject; 462 | PRODUCT_NAME = "$(TARGET_NAME)"; 463 | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; 464 | SWIFT_VERSION = 5.0; 465 | VERSIONING_SYSTEM = "apple-generic"; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 97C147031CF9000F007C117D /* Debug */, 476 | 97C147041CF9000F007C117D /* Release */, 477 | 249021D3217E4FDB00AE95B9 /* Profile */, 478 | ); 479 | defaultConfigurationIsVisible = 0; 480 | defaultConfigurationName = Release; 481 | }; 482 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | 97C147061CF9000F007C117D /* Debug */, 486 | 97C147071CF9000F007C117D /* Release */, 487 | 249021D4217E4FDB00AE95B9 /* Profile */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | /* End XCConfigurationList section */ 493 | }; 494 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 495 | } 496 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/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/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thealteria/flutter_getx_template/781c8ade7b218a1c248839e427366003f7f5f2bd/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_getx_template 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/app/common/constants.dart: -------------------------------------------------------------------------------- 1 | abstract class Constants { 2 | static const String baseUrl = String.fromEnvironment('B'); 3 | 4 | static const timeout = Duration(seconds: 5); 5 | static const String token = 'authToken'; 6 | 7 | static const String dummyImageUrl = 8 | 'https://i.picsum.photos/id/1084/536/354.jpg' 9 | '?grayscale&hmac=Ux7nzg19e1q35mlUVZjhCLxqkR30cC-CarVg-nlIf60'; 10 | static const String placeHolderBlurHash = 'LEHV6nWB2yk8pyo0adR*.7kCMdnj'; 11 | } 12 | -------------------------------------------------------------------------------- /lib/app/common/storage/storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_storage/get_storage.dart'; 2 | 3 | abstract class Storage { 4 | static final GetStorage _storage = GetStorage(); 5 | 6 | static GetStorage get storage => _storage; 7 | 8 | static Future saveValue(String key, dynamic value) => 9 | _storage.writeIfNull(key, value); 10 | 11 | static T? getValue(String key) => _storage.read(key); 12 | 13 | static bool hasData(String key) => _storage.hasData(key); 14 | 15 | static Future removeValue(String key) => _storage.remove(key); 16 | 17 | static Future clearStorage() => _storage.erase(); 18 | } 19 | -------------------------------------------------------------------------------- /lib/app/common/util/exports.dart: -------------------------------------------------------------------------------- 1 | library exports; 2 | 3 | export 'package:flutter_getx_template/app/common/storage/storage.dart'; 4 | export 'package:flutter_getx_template/app/common/util/extensions.dart'; 5 | export 'package:flutter_getx_template/app/common/util/utils.dart'; 6 | export 'package:flutter_getx_template/app/common/values/app_colors.dart'; 7 | export 'package:flutter_getx_template/app/common/values/app_images.dart'; 8 | export 'package:flutter_getx_template/app/common/values/strings.dart'; 9 | export 'package:flutter_getx_template/app/common/values/styles/app_text_style.dart'; 10 | export 'package:flutter_getx_template/app/common/values/styles/dimens.dart'; 11 | export 'package:flutter_getx_template/app/common/values/styles/theme.dart'; 12 | export 'package:flutter_screenutil/flutter_screenutil.dart'; 13 | -------------------------------------------------------------------------------- /lib/app/common/util/extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/constants.dart'; 3 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 4 | import 'package:flutter_getx_template/app/data/api_response.dart'; 5 | import 'package:flutter_getx_template/app/data/errors/api_error.dart'; 6 | import 'package:flutter_getx_template/app/data/interface_controller/api_interface_controller.dart'; 7 | import 'package:flutter_getx_template/app/routes/app_pages.dart'; 8 | import 'package:get/get.dart'; 9 | import 'package:intl/intl.dart'; 10 | 11 | import 'loading_dialog.dart'; 12 | 13 | abstract class Extensions {} 14 | 15 | extension BorderRadiusExt on num { 16 | BorderRadius get borderRadius => BorderRadius.circular(this.r); 17 | 18 | InputBorder outlineInputBorder({ 19 | BorderSide borderSide = BorderSide.none, 20 | }) => 21 | OutlineInputBorder( 22 | borderRadius: this.borderRadius, 23 | borderSide: borderSide, 24 | ); 25 | 26 | BorderSide borderSide({ 27 | Color? color, 28 | double? width, 29 | BorderStyle? style, 30 | }) => 31 | BorderSide( 32 | color: color ?? Colors.white, 33 | width: this.toDouble(), 34 | style: style ?? BorderStyle.solid, 35 | ); 36 | } 37 | 38 | extension HexColorExt on String { 39 | Color get fromHex { 40 | final buffer = StringBuffer(); 41 | if (this.length == 6 || this.length == 7) { 42 | buffer.write('ff'); 43 | } 44 | 45 | if (this.startsWith('#')) { 46 | buffer.write(this.replaceFirst('#', '')); 47 | } 48 | return Color(int.parse(buffer.toString(), radix: 16)); 49 | } 50 | } 51 | 52 | extension DateTimeFormatterExt on DateTime { 53 | String formatedDate({ 54 | String dateFormat = 'yyyy-MM-dd', 55 | }) { 56 | final formatter = DateFormat(dateFormat); 57 | return formatter.format(this); 58 | } 59 | } 60 | 61 | extension TimeOfDayExt on String { 62 | TimeOfDay getTimeOfDay({ 63 | int addMinutes = 0, 64 | }) => 65 | TimeOfDay.fromDateTime( 66 | DateFormat.jm().parse(this).add( 67 | Duration( 68 | minutes: addMinutes, 69 | ), 70 | ), 71 | ); 72 | } 73 | 74 | extension ImageExt on String { 75 | String get image => 'assets/images/$this.png'; 76 | 77 | Image imageAsset({ 78 | Size? size, 79 | BoxFit? fit, 80 | Color? color, 81 | }) => 82 | Image.asset( 83 | this, 84 | color: color, 85 | width: size?.width, 86 | height: size?.height, 87 | fit: fit, 88 | ); 89 | } 90 | 91 | extension FutureExt on Future?> { 92 | void futureValue( 93 | Function(T value) response, { 94 | Function(String? error)? onError, 95 | required VoidCallback retryFunction, 96 | bool showLoading = true, 97 | }) { 98 | final _interface = Get.find(); 99 | _interface.error = null; 100 | 101 | if (showLoading) LoadingDialog.showLoadingDialog(); 102 | 103 | this.timeout( 104 | Constants.timeout, 105 | onTimeout: () { 106 | LoadingDialog.closeLoadingDialog(); 107 | 108 | Utils.showSnackbar(Strings.connectionTimeout); 109 | 110 | _retry(_interface, retryFunction); 111 | 112 | throw const ApiError( 113 | type: ErrorType.connectTimeout, 114 | error: Strings.connectionTimeout, 115 | ); 116 | }, 117 | ).then((value) { 118 | LoadingDialog.closeLoadingDialog(); 119 | 120 | if (value?.body != null) { 121 | final result = ApiResponse.getResponse(value!); 122 | if (result != null) { 123 | response(result); 124 | } 125 | } 126 | 127 | _interface.update(); 128 | }).catchError((e) { 129 | LoadingDialog.closeLoadingDialog(); 130 | 131 | if (e == null) return; 132 | 133 | final String errorMessage = e is ApiError ? e.message : e.toString(); 134 | 135 | if (e is ApiError) { 136 | if ((e.type == ErrorType.connectTimeout || 137 | e.type == ErrorType.noConnection)) { 138 | _interface.error = e; 139 | 140 | _retry(_interface, retryFunction); 141 | } else { 142 | Utils.showDialog( 143 | errorMessage, 144 | onTap: errorMessage != Strings.unauthorize 145 | ? null 146 | : () { 147 | Storage.clearStorage(); 148 | Get.offAllNamed( 149 | Routes.HOME, 150 | //change the ROUTE to the LOGIN or SPLASH screen so that the 151 | //user can login again on UnauthorizeError error 152 | ); 153 | }, 154 | ); 155 | } 156 | } 157 | 158 | if (onError != null) { 159 | onError(errorMessage); 160 | } 161 | 162 | printError(info: 'catchError: error: $e\nerrorMessage: $errorMessage'); 163 | }); 164 | } 165 | 166 | void _retry( 167 | ApiInterfaceController _interface, 168 | VoidCallback retryFunction, 169 | ) { 170 | _interface.retry = retryFunction; 171 | _interface.update(); 172 | } 173 | } 174 | 175 | extension AlignWidgetExt on Widget { 176 | Widget align({ 177 | Alignment alignment = Alignment.center, 178 | }) => 179 | Align( 180 | alignment: alignment, 181 | child: this, 182 | ); 183 | } 184 | 185 | extension FormatDurationExt on int { 186 | String formatDuration() { 187 | final min = this ~/ 60; 188 | final sec = this % 60; 189 | return "${min.toString().padLeft(2, "0")}:${sec.toString().padLeft(2, "0")} min"; 190 | } 191 | } 192 | 193 | extension DebugLog on String { 194 | void debugLog() { 195 | return debugPrint( 196 | '\n******************************* DebugLog *******************************\n' 197 | ' $this' 198 | '\n******************************* DebugLog *******************************\n', 199 | wrapWidth: 1024, 200 | ); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /lib/app/common/util/initializer.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/services.dart'; 4 | import 'package:flutter/widgets.dart'; 5 | import 'package:flutter_getx_template/app/data/api_helper.dart'; 6 | import 'package:flutter_getx_template/app/data/api_helper_impl.dart'; 7 | import 'package:flutter_getx_template/app/data/interface_controller/api_interface_controller.dart'; 8 | import 'package:flutter_getx_template/app/modules/widgets/custom_error_widget.dart'; 9 | import 'package:get/get.dart'; 10 | import 'package:get_storage/get_storage.dart'; 11 | 12 | abstract class Initializer { 13 | static void init(VoidCallback runApp) { 14 | ErrorWidget.builder = (errorDetails) { 15 | return CustomErrorWidget( 16 | message: errorDetails.exceptionAsString(), 17 | ); 18 | }; 19 | 20 | runZonedGuarded(() async { 21 | WidgetsFlutterBinding.ensureInitialized(); 22 | FlutterError.onError = (details) { 23 | FlutterError.dumpErrorToConsole(details); 24 | Get.printInfo(info: details.stack.toString()); 25 | }; 26 | 27 | await _initServices(); 28 | runApp(); 29 | }, (error, stack) { 30 | Get.printInfo(info: 'runZonedGuarded: ${error.toString()}'); 31 | }); 32 | } 33 | 34 | static Future _initServices() async { 35 | try { 36 | await _initStorage(); 37 | 38 | _initScreenPreference(); 39 | } catch (err) { 40 | rethrow; 41 | } 42 | } 43 | 44 | static Future _initStorage() async { 45 | await GetStorage.init(); 46 | } 47 | 48 | static void _initScreenPreference() { 49 | SystemChrome.setPreferredOrientations([ 50 | DeviceOrientation.portraitUp, 51 | DeviceOrientation.portraitDown, 52 | ]); 53 | } 54 | } 55 | 56 | class InitialBindings extends Bindings { 57 | @override 58 | void dependencies() { 59 | Get.lazyPut( 60 | () => ApiHelperImpl(), 61 | ); 62 | 63 | Get.lazyPut( 64 | () => ApiInterfaceController(), 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/app/common/util/loading_dialog.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_getx_template/app/common/util/utils.dart'; 2 | import 'package:get/get.dart'; 3 | 4 | typedef CloseDialog = void Function(); 5 | 6 | abstract class LoadingDialog { 7 | static CloseDialog? _loadingDialog; 8 | 9 | static CloseDialog _showLoadingDialog() { 10 | Get.printInfo(info: 'initialized loading'); 11 | Utils.loadingDialog(); 12 | return Utils.closeDialog; 13 | } 14 | 15 | static void showLoadingDialog() { 16 | _loadingDialog = _showLoadingDialog(); 17 | Get.printInfo(info: 'start loading'); 18 | } 19 | 20 | static void closeLoadingDialog() { 21 | Get.printInfo(info: 'close loading'); 22 | _loadingDialog?.call(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/app/common/util/utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:math'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 6 | import 'package:flutter_getx_template/app/modules/widgets/custom_inkwell_widget.dart'; 7 | import 'package:flutter_getx_template/app/modules/widgets/custom_text_button.dart'; 8 | import 'package:get/get.dart'; 9 | import 'package:image_cropper/image_cropper.dart'; 10 | import 'package:image_picker/image_picker.dart'; 11 | 12 | abstract class Utils { 13 | static void showDialog( 14 | String? message, { 15 | String title = Strings.error, 16 | bool success = false, 17 | VoidCallback? onTap, 18 | }) => 19 | Get.defaultDialog( 20 | barrierDismissible: false, 21 | onWillPop: () async { 22 | Get.back(); 23 | 24 | onTap?.call(); 25 | 26 | return true; 27 | }, 28 | title: success ? Strings.success : title, 29 | content: Text( 30 | message ?? Strings.somethingWentWrong, 31 | textAlign: TextAlign.center, 32 | maxLines: 6, 33 | style: AppTextStyle.semiBoldStyle.copyWith( 34 | color: AppColors.mineShaft, 35 | fontSize: Dimens.fontSize16, 36 | ), 37 | ), 38 | confirm: Align( 39 | alignment: Alignment.centerRight, 40 | child: CustomInkwellWidget.text( 41 | onTap: () { 42 | Get.back(); 43 | 44 | onTap?.call(); 45 | }, 46 | title: Strings.ok, 47 | textStyle: AppTextStyle.buttonTextStyle.copyWith( 48 | fontSize: Dimens.fontSize18, 49 | ), 50 | ), 51 | ), 52 | ); 53 | 54 | static void showIconDialog( 55 | String title, 56 | String message, { 57 | Widget? imageWidget, 58 | VoidCallback? onTap, 59 | }) => 60 | Get.dialog( 61 | AlertDialog( 62 | title: 63 | imageWidget ?? const Icon(Icons.done), //add your icon/image here 64 | content: Column( 65 | mainAxisSize: MainAxisSize.min, 66 | children: [ 67 | Text( 68 | title, 69 | textAlign: TextAlign.center, 70 | style: AppTextStyle.semiBoldStyle.copyWith( 71 | color: Colors.black, 72 | fontSize: Dimens.fontSize24, 73 | ), 74 | ), 75 | SizedBox(height: 10.w), 76 | Text(message, 77 | textAlign: TextAlign.center, 78 | style: AppTextStyle.regularStyle.copyWith( 79 | color: AppColors.mineShaft, 80 | fontSize: Dimens.fontSize16, 81 | )), 82 | SizedBox(height: 20.w), 83 | CustomTextButton( 84 | title: Strings.ok, 85 | onPressed: () { 86 | Get.back(); 87 | 88 | onTap?.call(); 89 | }, 90 | ), 91 | ], 92 | ), 93 | ), 94 | barrierDismissible: false, 95 | ); 96 | 97 | static void timePicker( 98 | Function(String time) onSelectTime, { 99 | TimeOfDay? initialTime, 100 | }) { 101 | showTimePicker( 102 | context: Get.overlayContext!, 103 | initialTime: initialTime ?? 104 | TimeOfDay.fromDateTime( 105 | DateTime.now(), 106 | ), 107 | ).then((v) { 108 | if (v != null) { 109 | final _now = DateTime.now(); 110 | final _dateTime = DateTime( 111 | _now.year, 112 | _now.month, 113 | _now.day, 114 | v.hour, 115 | v.minute, 116 | ); 117 | 118 | onSelectTime(_dateTime.formatedDate(dateFormat: 'hh:mm aa')); 119 | } 120 | }); 121 | } 122 | 123 | static String getRandomString( 124 | int length, { 125 | bool isNumber = true, 126 | }) { 127 | final _chars = isNumber ? '1234567890' : 'abcdefghijklmnopqrstuvwxyz'; 128 | final _rnd = Random(); 129 | 130 | return String.fromCharCodes( 131 | Iterable.generate( 132 | length, 133 | (_) => _chars.codeUnitAt( 134 | _rnd.nextInt( 135 | _chars.length, 136 | ), 137 | ), 138 | ), 139 | ); 140 | } 141 | 142 | static void loadingDialog() { 143 | closeDialog(); 144 | 145 | Get.dialog( 146 | const Center( 147 | child: CircularProgressIndicator(), 148 | ), 149 | name: 'loadingDialog', 150 | ); 151 | } 152 | 153 | static void closeDialog() { 154 | if (Get.isDialogOpen == true) { 155 | Get.back(); 156 | } 157 | } 158 | 159 | static void closeSnackbar() { 160 | if (Get.isSnackbarOpen == true) { 161 | Get.back(); 162 | } 163 | } 164 | 165 | static void showSnackbar(String? message) { 166 | closeSnackbar(); 167 | 168 | Get.rawSnackbar(message: message); 169 | } 170 | 171 | static void closeKeyboard() { 172 | final currentFocus = Get.focusScope!; 173 | if (!currentFocus.hasPrimaryFocus) { 174 | currentFocus.unfocus(); 175 | } 176 | } 177 | 178 | static void goBackToScreen(String routeName) { 179 | Get.until( 180 | (route) => route.settings.name == routeName, 181 | ); 182 | } 183 | 184 | static Future showImagePicker({ 185 | required Function(File image) onGetImage, 186 | }) { 187 | return showModalBottomSheet( 188 | context: Get.context!, 189 | builder: (_) { 190 | return Padding( 191 | padding: EdgeInsets.all(10.w), 192 | child: Row( 193 | mainAxisSize: MainAxisSize.min, 194 | mainAxisAlignment: MainAxisAlignment.center, 195 | children: [ 196 | Expanded( 197 | child: InkWell( 198 | onTap: () { 199 | getImage(source: 2).then((v) { 200 | if (v != null) { 201 | onGetImage(v); 202 | Get.back(); 203 | } 204 | }); 205 | }, 206 | child: Column( 207 | mainAxisSize: MainAxisSize.min, 208 | children: [ 209 | Icon( 210 | Icons.image, 211 | size: 60.w, 212 | ), 213 | SizedBox(height: 10.h), 214 | Text( 215 | Strings.gallery, 216 | textAlign: TextAlign.center, 217 | style: AppTextStyle.semiBoldStyle.copyWith( 218 | color: AppColors.mineShaft, 219 | fontSize: Dimens.fontSize16, 220 | ), 221 | ) 222 | ], 223 | ), 224 | ), 225 | ), 226 | Expanded( 227 | child: InkWell( 228 | onTap: () { 229 | getImage().then((v) { 230 | if (v != null) { 231 | onGetImage(v); 232 | Get.back(); 233 | } 234 | }); 235 | }, 236 | child: Column( 237 | mainAxisSize: MainAxisSize.min, 238 | children: [ 239 | Icon( 240 | Icons.camera, 241 | size: 60.w, 242 | ), 243 | SizedBox( 244 | height: 10.h, 245 | ), 246 | Text( 247 | Strings.camera, 248 | textAlign: TextAlign.center, 249 | style: AppTextStyle.semiBoldStyle.copyWith( 250 | color: AppColors.mineShaft, 251 | fontSize: Dimens.fontSize16, 252 | ), 253 | ) 254 | ], 255 | ), 256 | ), 257 | ) 258 | ], 259 | ), 260 | ); 261 | }, 262 | ); 263 | } 264 | 265 | static Future getImage({int source = 1}) async { 266 | File? croppedFile; 267 | final picker = ImagePicker(); 268 | 269 | final pickedFile = await picker.pickImage( 270 | source: source == 1 ? ImageSource.camera : ImageSource.gallery, 271 | imageQuality: 60, 272 | ); 273 | 274 | if (pickedFile != null) { 275 | final image = File(pickedFile.path); 276 | 277 | croppedFile = await ImageCropper().cropImage( 278 | compressQuality: 50, 279 | sourcePath: image.path, 280 | aspectRatioPresets: [ 281 | CropAspectRatioPreset.square, 282 | CropAspectRatioPreset.ratio3x2, 283 | CropAspectRatioPreset.original, 284 | CropAspectRatioPreset.ratio4x3, 285 | CropAspectRatioPreset.ratio16x9 286 | ], 287 | androidUiSettings: const AndroidUiSettings( 288 | toolbarColor: Colors.transparent, 289 | toolbarWidgetColor: Colors.transparent, 290 | initAspectRatio: CropAspectRatioPreset.original, 291 | lockAspectRatio: false, 292 | ), 293 | iosUiSettings: const IOSUiSettings( 294 | minimumAspectRatio: 0.1, 295 | aspectRatioLockDimensionSwapEnabled: true, 296 | ), 297 | ); 298 | } 299 | 300 | return croppedFile; 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /lib/app/common/util/validators.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 2 | import 'package:get/get.dart'; 3 | 4 | abstract class Validators { 5 | static String? validateEmpty(String? v) { 6 | if (v!.isEmpty) { 7 | return Strings.fieldCantBeEmpty; 8 | } else { 9 | return null; 10 | } 11 | } 12 | 13 | static String? validateTEmpty(T? v) { 14 | if (v == null) { 15 | return Strings.fieldCantBeEmpty; 16 | } else { 17 | return null; 18 | } 19 | } 20 | 21 | static String? validateEmail(String? v) { 22 | if (v!.isEmpty) { 23 | return Strings.emailCantBeEmpty; 24 | } else if (!GetUtils.isEmail(v)) { 25 | return Strings.enterValidEmail; 26 | } else { 27 | return null; 28 | } 29 | } 30 | 31 | static String? validatePhone(String? v) { 32 | if (v!.isEmpty) { 33 | return Strings.fieldCantBeEmpty; 34 | } else if (v.length != 10) { 35 | return Strings.enterValidNumber; 36 | } else { 37 | return null; 38 | } 39 | } 40 | 41 | static String? validateEmailPhone(String? v) { 42 | if (v!.isEmpty) { 43 | return Strings.fieldCantBeEmpty; 44 | } else if (GetUtils.isNumericOnly(v)) { 45 | return validatePhone(v); 46 | } else { 47 | return validateEmail(v); 48 | } 49 | } 50 | 51 | static String? validatePassword(String? v) { 52 | if (v!.isEmpty) { 53 | return Strings.passwordCantBeEmpty; 54 | } else if (v.length < 8) { 55 | return Strings.passwordValidation; 56 | } else { 57 | return null; 58 | } 59 | } 60 | 61 | static String? validateConfirmPassword(String? v, String password) { 62 | if (v!.isEmpty || password.isEmpty) { 63 | return Strings.passwordCantBeEmpty; 64 | } else if (v.length < 8 || password.length < 8 || v != password) { 65 | return Strings.confirmPasswordValidation; 66 | } else { 67 | return null; 68 | } 69 | } 70 | 71 | static String? validateCheckbox({ 72 | bool v = false, 73 | String error = Strings.checkboxValidation, 74 | }) { 75 | if (!v) { 76 | return error; 77 | } else { 78 | return null; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /lib/app/common/values/app_colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | abstract class AppColors { 4 | static const Color kPrimaryColor = Color(0xFF1976D2); 5 | static const Color mineShaft = Color(0xFF2B2B2B); 6 | static const Color doveGray = Color(0xFF646464); 7 | static const Color caribbeanGreen = Color(0xFF06C5AC); 8 | static const Color amaranth = Color(0xFFea435d); 9 | static const Color black = Colors.black; 10 | static const Color white = Colors.white; 11 | } 12 | -------------------------------------------------------------------------------- /lib/app/common/values/app_images.dart: -------------------------------------------------------------------------------- 1 | abstract class AppImages { 2 | ///add app images here 3 | 4 | static const String icGallery = 'assets/images/ic_gallery.png'; 5 | } 6 | -------------------------------------------------------------------------------- /lib/app/common/values/strings.dart: -------------------------------------------------------------------------------- 1 | abstract class Strings { 2 | static const unknownError = 'Unknow error! Please try again after some time.'; 3 | static const connectionTimeout = 4 | 'Connection timeout. Please try again after some time.'; 5 | static const noConnection = 'No connection. Please turn on your internet!'; 6 | static const unauthorize = 'Unauthorize. Please login again!'; 7 | 8 | static const String appName = 'Getx Template'; 9 | static const String ok = 'Ok'; 10 | static const String error = 'Error'; 11 | static const String noInternet = 'No internet. Please try again later.'; 12 | static const String logOut = 'Log out'; 13 | static const String retry = 'Retry'; 14 | static const String somethingWentWrong = 'Something went wrong.'; 15 | static const String home = 'Home'; 16 | static const emailAddress = 'Email Address'; 17 | static const mobileNumber = 'Mobile Number'; 18 | static const String emailOrMobile = '$emailAddress or $mobileNumber'; 19 | static const String cantBeEmpty = "can't be empty."; 20 | static const String fieldCantBeEmpty = 'Field $cantBeEmpty'; 21 | static const String numberCantBeEmpty = '$emailOrMobile $cantBeEmpty'; 22 | static const String emailCantBeEmpty = 'Email $cantBeEmpty'; 23 | static const String enterValid = 'Please enter a valid'; 24 | static const String enterValidNumber = '$enterValid $mobileNumber.'; 25 | static const String enterValidEmail = '$enterValid email.'; 26 | static const String password = 'Password'; 27 | static const String confirmPassword = 'Confirm $password'; 28 | static const String enterPassword = 'Enter $password'; 29 | static const String passwordCantBeEmpty = '$password $cantBeEmpty'; 30 | static const String passwordValidation = 31 | '$password must be at least 8 characters long.'; 32 | static const confirmPasswordValidation = 33 | '$password and Confirm password should be same.'; 34 | static const otpValidation = 'Invalid OTP'; 35 | static const gallery = 'Gallery'; 36 | static const camera = 'Camera'; 37 | static const mobile = 'Mobile'; 38 | static const from = 'From'; 39 | static const to = 'To'; 40 | static const success = 'Success'; 41 | static const checkboxValidation = 'Dummy Checkbox Validation Message'; 42 | } 43 | -------------------------------------------------------------------------------- /lib/app/common/values/styles/app_text_style.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'dimens.dart'; 4 | 5 | abstract class AppTextStyle { 6 | /// NAME SIZE WEIGHT SPACING 7 | /// headline1 96.0 light -1.5 8 | static final TextStyle headline1 = lightStyle.copyWith( 9 | fontSize: Dimens.fontSize96, 10 | letterSpacing: -1.5, 11 | ); 12 | 13 | /// NAME SIZE WEIGHT SPACING 14 | /// headline2 60.0 light -0.5 15 | static final TextStyle headline2 = lightStyle.copyWith( 16 | fontSize: Dimens.fontSize60, 17 | letterSpacing: -0.5, 18 | ); 19 | 20 | /// NAME SIZE WEIGHT SPACING 21 | /// headline3 48.0 regular 0.0 22 | static final TextStyle headline3 = regularStyle.copyWith( 23 | fontSize: Dimens.fontSize48, 24 | letterSpacing: 0, 25 | ); 26 | 27 | /// NAME SIZE WEIGHT SPACING 28 | /// headline4 34.0 regular 0.25 29 | static final TextStyle headline4 = regularStyle.copyWith( 30 | fontSize: Dimens.fontSize34, 31 | letterSpacing: 0.25, 32 | ); 33 | 34 | /// NAME SIZE WEIGHT SPACING 35 | /// headline5 24.0 regular 0.0 36 | static final TextStyle headline5 = regularStyle.copyWith( 37 | fontSize: Dimens.fontSize24, 38 | letterSpacing: 0, 39 | ); 40 | 41 | /// NAME SIZE WEIGHT SPACING 42 | /// headline6 20.0 medium 0.15 43 | static final TextStyle headline6 = mediumStyle.copyWith( 44 | fontSize: Dimens.fontSize20, 45 | letterSpacing: 0.15, 46 | ); 47 | 48 | /// NAME SIZE WEIGHT SPACING 49 | /// subtitle1 16.0 regular 0.15 50 | static final TextStyle subtitle1 = regularStyle.copyWith( 51 | fontSize: Dimens.fontSize16, 52 | letterSpacing: 0.15, 53 | ); 54 | 55 | /// NAME SIZE WEIGHT SPACING 56 | /// subtitle2 14.0 medium 0.1 57 | static final TextStyle subtitle2 = mediumStyle.copyWith( 58 | fontSize: Dimens.fontSize14, 59 | letterSpacing: 0.1, 60 | ); 61 | 62 | /// NAME SIZE WEIGHT SPACING 63 | /// body1 16.0 regular 0.5 (bodyText1) 64 | static final TextStyle body1 = regularStyle.copyWith( 65 | fontSize: Dimens.fontSize16, 66 | letterSpacing: 0.5, 67 | ); 68 | 69 | /// NAME SIZE WEIGHT SPACING 70 | /// body2 14.0 regular 0.25 (bodyText2) 71 | static final TextStyle body2 = regularStyle.copyWith( 72 | fontSize: Dimens.fontSize14, 73 | letterSpacing: 0.25, 74 | ); 75 | 76 | /// NAME SIZE WEIGHT SPACING 77 | /// button 14.0 medium 1.25 78 | static final TextStyle button = mediumStyle.copyWith( 79 | fontSize: Dimens.fontSize14, 80 | letterSpacing: 1.25, 81 | ); 82 | 83 | /// NAME SIZE WEIGHT SPACING 84 | /// caption 12.0 regular 0.4 85 | static final TextStyle caption = regularStyle.copyWith( 86 | fontSize: Dimens.fontSize12, 87 | letterSpacing: .4, 88 | ); 89 | 90 | /// NAME SIZE WEIGHT SPACING 91 | /// overline 10.0 regular 1.5 92 | static final TextStyle overline = regularStyle.copyWith( 93 | fontSize: Dimens.fontSize10, 94 | letterSpacing: 1.5, 95 | ); 96 | 97 | static final TextStyle lightStyle = _textStyle.copyWith( 98 | fontWeight: FontWeight.w300, 99 | ); 100 | 101 | static final TextStyle regularStyle = _textStyle.copyWith( 102 | fontWeight: FontWeight.w400, 103 | ); 104 | 105 | static final TextStyle mediumStyle = _textStyle.copyWith( 106 | fontWeight: FontWeight.w500, 107 | ); 108 | 109 | static final TextStyle semiBoldStyle = _textStyle.copyWith( 110 | fontWeight: FontWeight.w600, 111 | ); 112 | 113 | static final TextStyle boldStyle = _textStyle.copyWith( 114 | fontWeight: FontWeight.w700, 115 | ); 116 | 117 | static final TextStyle buttonTextStyle = _textStyle.copyWith( 118 | fontSize: Dimens.fontSize16, 119 | fontWeight: FontWeight.w700, 120 | ); 121 | 122 | static const TextStyle _textStyle = TextStyle( 123 | color: Colors.black, 124 | ); 125 | 126 | static TextTheme get textTheme => TextTheme( 127 | headline1: headline1, 128 | headline2: headline2, 129 | headline3: headline3, 130 | headline4: headline4, 131 | headline5: headline5, 132 | headline6: headline6, 133 | subtitle1: subtitle1, 134 | subtitle2: subtitle2, 135 | bodyText1: body1, 136 | bodyText2: body2, 137 | caption: caption, 138 | button: button, 139 | overline: overline, 140 | ); 141 | } 142 | -------------------------------------------------------------------------------- /lib/app/common/values/styles/dimens.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 2 | 3 | abstract class Dimens { 4 | static final double fontSize10 = 10.sp; 5 | static final double fontSize12 = 12.sp; 6 | static final double fontSize13 = 13.sp; 7 | static final double fontSize14 = 14.sp; 8 | static final double fontSize15 = 15.sp; 9 | static final double fontSize16 = 16.sp; 10 | static final double fontSize18 = 18.sp; 11 | static final double fontSize20 = 20.sp; 12 | static final double fontSize22 = 22.sp; 13 | static final double fontSize24 = 24.sp; 14 | static final double fontSize26 = 26.sp; 15 | static final double fontSize28 = 28.sp; 16 | static final double fontSize30 = 30.sp; 17 | static final double fontSize32 = 32.sp; 18 | static final double fontSize34 = 34.sp; 19 | static final double fontSize48 = 48.sp; 20 | static final double fontSize60 = 60.sp; 21 | static final double fontSize96 = 96.sp; 22 | } 23 | -------------------------------------------------------------------------------- /lib/app/common/values/styles/theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/extensions.dart'; 3 | import 'package:flutter_getx_template/app/common/values/app_colors.dart'; 4 | import 'package:flutter_getx_template/app/common/values/styles/app_text_style.dart'; 5 | import 'package:flutter_getx_template/app/common/values/styles/dimens.dart'; 6 | import 'package:flutter_screenutil/flutter_screenutil.dart'; 7 | 8 | abstract class AppTheme { 9 | static ThemeData get theme { 10 | final inputBorder = 16.outlineInputBorder( 11 | borderSide: 3.borderSide(), 12 | ); 13 | 14 | final hintStyle = AppTextStyle.semiBoldStyle.copyWith( 15 | color: AppColors.doveGray, 16 | fontSize: Dimens.fontSize14, 17 | ); 18 | 19 | return ThemeData( 20 | brightness: Brightness.light, 21 | primaryColor: AppColors.kPrimaryColor, 22 | visualDensity: VisualDensity.adaptivePlatformDensity, 23 | appBarTheme: const AppBarTheme( 24 | color: AppColors.kPrimaryColor, 25 | ), 26 | primaryTextTheme: AppTextStyle.textTheme, 27 | buttonTheme: ButtonThemeData( 28 | buttonColor: AppColors.kPrimaryColor, 29 | height: 45.h, 30 | textTheme: ButtonTextTheme.primary, 31 | shape: RoundedRectangleBorder( 32 | borderRadius: 23.borderRadius, 33 | ), 34 | ), 35 | textButtonTheme: TextButtonThemeData( 36 | style: ButtonStyle( 37 | padding: MaterialStateProperty.resolveWith( 38 | (_) => EdgeInsets.zero, 39 | ), 40 | overlayColor: MaterialStateProperty.resolveWith( 41 | (Set states) { 42 | if (states.contains(MaterialState.pressed)) { 43 | return Colors.white.withOpacity(.14); 44 | } 45 | 46 | return null; 47 | }, 48 | ), 49 | textStyle: MaterialStateProperty.resolveWith( 50 | (_) => AppTextStyle.buttonTextStyle, 51 | ), 52 | shape: MaterialStateProperty.resolveWith( 53 | (states) => RoundedRectangleBorder( 54 | borderRadius: 10.borderRadius, 55 | ), 56 | ), 57 | backgroundColor: MaterialStateProperty.resolveWith( 58 | (Set states) { 59 | if (states.contains(MaterialState.disabled)) { 60 | return AppColors.doveGray; 61 | } 62 | return null; 63 | }, 64 | ), 65 | ), 66 | ), 67 | elevatedButtonTheme: ElevatedButtonThemeData( 68 | style: ButtonStyle( 69 | padding: MaterialStateProperty.resolveWith( 70 | (_) => EdgeInsets.zero, 71 | ), 72 | overlayColor: MaterialStateProperty.resolveWith( 73 | (Set states) { 74 | if (states.contains(MaterialState.pressed)) { 75 | return Colors.white.withOpacity(.14); 76 | } 77 | 78 | return null; 79 | }, 80 | ), 81 | textStyle: MaterialStateProperty.resolveWith( 82 | (_) => AppTextStyle.buttonTextStyle, 83 | ), 84 | shape: MaterialStateProperty.resolveWith( 85 | (states) => RoundedRectangleBorder( 86 | borderRadius: 10.borderRadius, 87 | ), 88 | ), 89 | ), 90 | ), 91 | floatingActionButtonTheme: const FloatingActionButtonThemeData( 92 | elevation: 4, 93 | backgroundColor: AppColors.kPrimaryColor, 94 | ), 95 | textTheme: TextTheme( 96 | subtitle1: AppTextStyle.regularStyle.copyWith( 97 | color: AppColors.mineShaft, 98 | fontSize: Dimens.fontSize14, 99 | ), 100 | ), 101 | inputDecorationTheme: InputDecorationTheme( 102 | filled: true, 103 | contentPadding: const EdgeInsets.symmetric( 104 | horizontal: 12, 105 | vertical: 3, 106 | ), 107 | prefixStyle: AppTextStyle.regularStyle.copyWith( 108 | fontSize: Dimens.fontSize14, 109 | color: AppColors.black, 110 | ), 111 | hintStyle: hintStyle, 112 | labelStyle: hintStyle, 113 | enabledBorder: inputBorder, 114 | disabledBorder: inputBorder, 115 | focusedBorder: inputBorder, 116 | border: inputBorder, 117 | ), 118 | cardTheme: CardTheme( 119 | color: Colors.white.withOpacity(0.85), 120 | shape: RoundedRectangleBorder( 121 | borderRadius: 10.borderRadius, 122 | ), 123 | ), 124 | dialogTheme: DialogTheme( 125 | backgroundColor: Colors.white, 126 | shape: RoundedRectangleBorder( 127 | borderRadius: 20.borderRadius, 128 | ), 129 | ), 130 | bottomSheetTheme: BottomSheetThemeData( 131 | backgroundColor: Colors.white, 132 | shape: RoundedRectangleBorder( 133 | borderRadius: BorderRadius.only( 134 | topLeft: Radius.circular(23.r), 135 | topRight: Radius.circular(23.r), 136 | ), 137 | ), 138 | ), 139 | colorScheme: ColorScheme.fromSwatch().copyWith( 140 | secondary: AppColors.kPrimaryColor, 141 | ), 142 | ); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /lib/app/data/api_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | 3 | export 'package:flutter_getx_template/app/common/util/extensions.dart'; 4 | export 'package:flutter_getx_template/app/common/util/utils.dart'; 5 | 6 | abstract class ApiHelper { 7 | static ApiHelper get to => Get.find(); 8 | 9 | Future getPosts(); 10 | } 11 | -------------------------------------------------------------------------------- /lib/app/data/api_helper_impl.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_getx_template/app/common/constants.dart'; 4 | import 'package:flutter_getx_template/app/common/storage/storage.dart'; 5 | import 'package:get/get.dart'; 6 | 7 | import 'api_helper.dart'; 8 | 9 | class ApiHelperImpl extends GetConnect with ApiHelper { 10 | @override 11 | void onInit() { 12 | httpClient.baseUrl = Constants.baseUrl; 13 | httpClient.timeout = Constants.timeout; 14 | 15 | addRequestModifier(); 16 | 17 | httpClient.addResponseModifier((request, response) { 18 | printInfo( 19 | info: 'Status Code: ${response.statusCode}\n' 20 | 'Data: ${response.bodyString?.toString() ?? ''}', 21 | ); 22 | 23 | return response; 24 | }); 25 | } 26 | 27 | void addRequestModifier() { 28 | httpClient.addRequestModifier((request) { 29 | if (Storage.hasData(Constants.token)) { 30 | request.headers['Authorization'] = Storage.getValue(Constants.token); 31 | } 32 | 33 | printInfo( 34 | info: 'REQUEST ║ ${request.method.toUpperCase()}\n' 35 | 'url: ${request.url}\n' 36 | 'Headers: ${request.headers}\n' 37 | 'Body: ${request.files?.toString() ?? ''}\n', 38 | ); 39 | 40 | return request; 41 | }); 42 | } 43 | 44 | @override 45 | Future> getPosts() { 46 | return get('posts'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/app/data/api_response.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:convert'; 3 | 4 | import 'package:flutter_getx_template/app/common/values/strings.dart'; 5 | import 'package:get/get.dart'; 6 | import 'package:get/get_connect/http/src/status/http_status.dart'; 7 | 8 | import 'errors/api_error.dart'; 9 | 10 | abstract class ApiResponse { 11 | static T? getResponse(Response response) { 12 | final status = response.status; 13 | 14 | if (status.connectionError) { 15 | throw const ApiError( 16 | type: ErrorType.noConnection, 17 | error: Strings.noConnection, 18 | ); 19 | } 20 | 21 | if (response.bodyString == null) throw const ApiError(); 22 | 23 | try { 24 | String result = response.bodyString!; 25 | final res = jsonDecode(result); 26 | 27 | if (response.isOk) { 28 | if (res is Map) { 29 | if (res['errorcode'] != null && 30 | res['errorcode'].toString().isNotEmpty) { 31 | if (res['errorcode'].toString() == 'invalidtoken') { 32 | throw const ApiError( 33 | type: ErrorType.response, 34 | error: Strings.unauthorize, 35 | ); 36 | } else { 37 | throw ApiError( 38 | type: ErrorType.response, 39 | error: res['msg']?.toString() ?? 40 | (res['message']?.toString() ?? Strings.unknownError), 41 | ); 42 | } 43 | } 44 | } 45 | 46 | return response.body; 47 | } else { 48 | if (status.isServerError) { 49 | throw const ApiError(); 50 | } else if (status.code == HttpStatus.requestTimeout) { 51 | throw const ApiError( 52 | type: ErrorType.connectTimeout, 53 | error: Strings.connectionTimeout, 54 | ); 55 | } else if (response.unauthorized) { 56 | throw ApiError( 57 | type: ErrorType.unauthorize, 58 | error: res['msg']?.toString() ?? Strings.unauthorize, 59 | ); 60 | } else { 61 | throw ApiError( 62 | type: ErrorType.response, 63 | error: res['msg']?.toString() ?? Strings.unknownError, 64 | ); 65 | } 66 | } 67 | } on FormatException { 68 | throw const ApiError( 69 | type: ErrorType.unknownError, 70 | error: Strings.unknownError, 71 | ); 72 | } on TimeoutException catch (e) { 73 | throw ApiError( 74 | type: ErrorType.connectTimeout, 75 | error: e.message?.toString() ?? Strings.connectionTimeout, 76 | ); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/app/data/errors/api_error.dart: -------------------------------------------------------------------------------- 1 | enum ErrorType { 2 | /// It occurs when url is opened timeout. 3 | connectTimeout, 4 | 5 | /// It occurs when url is noConnection. 6 | noConnection, 7 | 8 | /// When the server response, but with a incorrect status, such as 404, 503... 9 | response, 10 | 11 | /// When the request is cancelled, dio will throw a error with this type. 12 | cancel, 13 | 14 | /// When the request is unauthorize. 15 | unauthorize, 16 | 17 | /// Default error type, Some other Error. In this case, you can 18 | /// use the ApiError.error if it is not null. 19 | unknownError, 20 | } 21 | 22 | /// ApiError describes the error info when request failed. 23 | class ApiError implements Exception { 24 | const ApiError({ 25 | this.type = ErrorType.unknownError, 26 | this.error, 27 | }); 28 | 29 | final ErrorType type; 30 | 31 | /// The original error/exception object; It's usually not null when `type` 32 | /// is ErrorType.DEFAULT 33 | final dynamic error; 34 | 35 | String get message => (error?.toString() ?? ''); 36 | 37 | @override 38 | String toString() { 39 | var msg = '$type\nmessage: $message'; 40 | return msg; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/app/data/interface_controller/api_interface_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter_getx_template/app/data/errors/api_error.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | class ApiInterfaceController extends GetxController { 6 | ApiError? error; 7 | 8 | VoidCallback? retry; 9 | 10 | void onRetryTap() { 11 | error = null; 12 | retry?.call(); 13 | update(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/app/modules/home/bindings/home_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_getx_template/app/modules/home/controllers/home_controller.dart'; 2 | import 'package:get/get.dart'; 3 | 4 | class HomeBinding extends Bindings { 5 | @override 6 | void dependencies() { 7 | Get.lazyPut( 8 | () => HomeController(), 9 | ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/app/modules/home/controllers/home_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_getx_template/app/common/storage/storage.dart'; 2 | import 'package:flutter_getx_template/app/data/api_helper.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | class HomeController extends GetxController { 6 | final ApiHelper _apiHelper = ApiHelper.to; 7 | 8 | final RxList _dataList = RxList(); 9 | List get dataList => _dataList; 10 | set dataList(List dataList) => _dataList.addAll(dataList); 11 | 12 | @override 13 | void onReady() { 14 | super.onReady(); 15 | 16 | getPosts(); 17 | } 18 | 19 | void getPosts() { 20 | _apiHelper.getPosts().futureValue( 21 | (value) => dataList = value, 22 | retryFunction: getPosts, 23 | ); 24 | } 25 | 26 | void onEditProfileClick() { 27 | Get.back(); 28 | } 29 | 30 | void onFaqsClick() { 31 | Get.back(); 32 | } 33 | 34 | void onLogoutClick() { 35 | Storage.clearStorage(); 36 | // Get.offAllNamed(Routes.HOME); 37 | //Specify the INITIAL SCREEN you want to display to the user after logout 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/app/modules/home/views/home_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/modules/home/controllers/home_controller.dart'; 4 | import 'package:flutter_getx_template/app/modules/widgets/base_widget.dart'; 5 | import 'package:flutter_getx_template/app/modules/widgets/custom_appbar_widget.dart'; 6 | import 'package:get/get.dart'; 7 | 8 | class HomeView extends GetView { 9 | const HomeView({Key? key}) : super(key: key); 10 | 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: CustomAppbarWidget( 15 | addBackButton: false, 16 | title: Strings.home, 17 | ), 18 | body: Obx( 19 | () { 20 | return ListView.separated( 21 | separatorBuilder: (context, index) => SizedBox(height: 10.h), 22 | itemCount: controller.dataList.length, 23 | padding: const EdgeInsets.all(16), 24 | shrinkWrap: true, 25 | itemBuilder: (context, index) { 26 | final dynamic _data = controller.dataList[index]; 27 | 28 | return Column( 29 | mainAxisSize: MainAxisSize.min, 30 | crossAxisAlignment: CrossAxisAlignment.start, 31 | children: [ 32 | Text( 33 | 'Title: ${_data['title'].toString()}', 34 | ), 35 | SizedBox(height: 5.h), 36 | Text( 37 | 'Body: ${_data['body'].toString()}', 38 | ), 39 | ], 40 | ); 41 | }, 42 | ); 43 | }, 44 | ), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/base_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/data/interface_controller/api_interface_controller.dart'; 3 | import 'package:flutter_getx_template/app/modules/widgets/custom_retry_widget.dart'; 4 | import 'package:get/get.dart'; 5 | 6 | export 'package:flutter_getx_template/app/common/util/exports.dart'; 7 | 8 | class BaseWidget extends StatelessWidget { 9 | ///A widget with only custom retry button widget. 10 | final Widget child; 11 | 12 | const BaseWidget({ 13 | Key? key, 14 | required this.child, 15 | }) : super(key: key); 16 | @override 17 | Widget build(BuildContext context) { 18 | return GetBuilder( 19 | builder: (c) => Stack( 20 | children: [ 21 | Positioned.fill( 22 | child: child, 23 | ), 24 | Visibility( 25 | visible: c.retry != null && c.error != null, 26 | child: Positioned.fill( 27 | child: Scaffold( 28 | body: CustomRetryWidget( 29 | onPressed: c.onRetryTap, 30 | ), 31 | ), 32 | ), 33 | ), 34 | ], 35 | ), 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_appbar_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/modules/widgets/custom_back_button.dart'; 4 | 5 | class CustomAppbarWidget extends PreferredSize { 6 | final String? title; 7 | final Color? backgroundColor, backbuttonColor, textColor; 8 | final TextStyle? textStyle; 9 | final List? actions; 10 | final Function()? onActionButtonTap, onBackPress; 11 | final double? actionButtonWidth; 12 | final Widget? titleWidget, leading, bottom; 13 | final bool addBackButton; 14 | final bool? centerTitle; 15 | 16 | CustomAppbarWidget({ 17 | Key? key, 18 | this.title, 19 | this.titleWidget, 20 | this.leading, 21 | this.addBackButton = true, 22 | this.onBackPress, 23 | this.backgroundColor = AppColors.kPrimaryColor, 24 | this.backbuttonColor = Colors.white, 25 | this.textColor, 26 | this.textStyle, 27 | this.actions, 28 | this.onActionButtonTap, 29 | this.actionButtonWidth = 100, 30 | this.bottom, 31 | this.centerTitle, 32 | }) : assert( 33 | textColor == null || textStyle == null, 34 | 'Cannot provide both a textColor and a textStyle\n' 35 | 'To provide both, use "textStyle: TextStyle(color: color)".', 36 | ), 37 | super( 38 | key: key, 39 | child: const SizedBox.shrink(), 40 | preferredSize: 41 | Size.fromHeight(bottom == null ? kToolbarHeight : 98.h), 42 | ); 43 | 44 | @override 45 | Widget build(BuildContext context) { 46 | return AppBar( 47 | centerTitle: centerTitle, 48 | elevation: 0, 49 | actions: actions, 50 | actionsIconTheme: IconThemeData( 51 | size: 20.w, 52 | ), 53 | bottom: bottom == null 54 | ? null 55 | : PreferredSize( 56 | preferredSize: Size.fromHeight(100.h), 57 | child: bottom!, 58 | ), 59 | leading: addBackButton 60 | ? CustomBackButton( 61 | leading: leading, 62 | onBackTap: onBackPress, 63 | backbuttonColor: backbuttonColor, 64 | ) 65 | : null, 66 | leadingWidth: 45.w, 67 | backgroundColor: backgroundColor, 68 | title: title == null 69 | ? (titleWidget ?? const SizedBox.shrink()) 70 | : Text( 71 | title!, 72 | style: textStyle ?? 73 | AppTextStyle.boldStyle.copyWith( 74 | color: textColor ?? 75 | (backgroundColor == Colors.white 76 | ? AppColors.mineShaft 77 | : Colors.white), 78 | fontSize: Dimens.fontSize18, 79 | ), 80 | ), 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_back_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | class CustomBackButton extends StatelessWidget { 6 | final Widget? leading; 7 | final Function()? onBackTap; 8 | final Color? backbuttonColor; 9 | 10 | const CustomBackButton({ 11 | Key? key, 12 | this.leading, 13 | this.onBackTap, 14 | this.backbuttonColor, 15 | }) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return IconButton( 20 | onPressed: onBackTap ?? () => Get.back(), 21 | icon: leading ?? 22 | Icon( 23 | Icons.arrow_back, 24 | color: backbuttonColor ?? Get.theme.primaryIconTheme.color, 25 | ).paddingOnly(left: 10.w), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_card_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/modules/widgets/stroke_background.dart'; 4 | 5 | class CustomCardWidget extends StatelessWidget { 6 | final Widget? trailing; 7 | final String? title, trailingText, leadingImage; 8 | final Function() onTap; 9 | final bool addForwardIcon; 10 | 11 | const CustomCardWidget({ 12 | Key? key, 13 | this.leadingImage, 14 | required this.title, 15 | this.trailing, 16 | required this.onTap, 17 | this.trailingText, 18 | this.addForwardIcon = true, 19 | }) : assert(trailingText == null || trailing == null, Strings.error), 20 | super(key: key); 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return StrokeBackground( 25 | onTap: onTap, 26 | height: 68, 27 | child: Row( 28 | children: [ 29 | if (leadingImage != null) ...[ 30 | leadingImage!.imageAsset( 31 | size: Size(24.w, 24.w), 32 | ), 33 | SizedBox(width: 10.w), 34 | ], 35 | Text( 36 | title!, 37 | style: AppTextStyle.regularStyle.copyWith( 38 | color: AppColors.black, 39 | fontSize: Dimens.fontSize16, 40 | ), 41 | ), 42 | if (trailing != null) ...[ 43 | const Spacer(), 44 | trailing! 45 | ] else if (trailingText != null) ...[ 46 | const Spacer(), 47 | CircleAvatar( 48 | radius: 12.r, 49 | backgroundColor: AppColors.amaranth, 50 | child: Text( 51 | trailingText!, 52 | style: AppTextStyle.regularStyle.copyWith( 53 | color: Colors.white, 54 | ), 55 | ), 56 | ), 57 | ] else 58 | const SizedBox.shrink(), 59 | if (addForwardIcon) ...[ 60 | if (trailing == null && trailingText == null) 61 | const Spacer() 62 | else 63 | SizedBox(width: 10.w), 64 | const Icon(Icons.arrow_forward_ios_sharp), 65 | ], 66 | ], 67 | ), 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_checkbox_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/validators.dart'; 3 | 4 | class CustomCheckboxWidget extends FormField { 5 | CustomCheckboxWidget({ 6 | Key? key, 7 | required bool value, 8 | required FormFieldSetter onSaved, 9 | required Widget titleWidget, 10 | }) : super( 11 | key: key, 12 | initialValue: value, 13 | onSaved: onSaved, 14 | autovalidateMode: AutovalidateMode.onUserInteraction, 15 | validator: (v) => Validators.validateCheckbox(v: v!), 16 | builder: (state) { 17 | return CheckboxListTile( 18 | dense: state.hasError, 19 | value: state.value, 20 | contentPadding: EdgeInsets.zero, 21 | controlAffinity: ListTileControlAffinity.leading, 22 | onChanged: state.didChange, 23 | title: titleWidget, 24 | subtitle: state.hasError 25 | ? Builder( 26 | builder: (_) => Text( 27 | state.errorText!, 28 | style: TextStyle(color: Theme.of(_).errorColor), 29 | ), 30 | ) 31 | : null, 32 | ); 33 | }, 34 | ); 35 | } 36 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_drawer_header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/modules/home/controllers/home_controller.dart'; 4 | import 'package:flutter_getx_template/app/modules/widgets/custom_row_text_widget.dart'; 5 | 6 | class CustomDrawerHeader extends StatelessWidget { 7 | final HomeController homeController; 8 | 9 | const CustomDrawerHeader({ 10 | Key? key, 11 | required this.homeController, 12 | }) : super(key: key); 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | padding: EdgeInsets.fromLTRB(15.w, 15.w, 15.w, 7.w), 18 | child: Row( 19 | children: [ 20 | ClipRRect( 21 | borderRadius: 5.borderRadius, 22 | child: FadeInImage.assetNetwork( 23 | placeholder: AppImages.icGallery, 24 | width: 60.w, 25 | height: 60.w, 26 | fit: BoxFit.cover, 27 | image: 'https://dummyimage.com/600x400/000/fff.jpg', 28 | imageErrorBuilder: (_, e, s) => const Icon(Icons.offline_bolt), 29 | ), 30 | ), 31 | Expanded( 32 | child: Padding( 33 | padding: EdgeInsets.all(15.w), 34 | child: Column( 35 | mainAxisSize: MainAxisSize.min, 36 | crossAxisAlignment: CrossAxisAlignment.start, 37 | children: [ 38 | Row( 39 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 40 | children: [ 41 | Text( 42 | 'First name', 43 | style: AppTextStyle.semiBoldStyle.copyWith( 44 | fontSize: Dimens.fontSize16, 45 | ), 46 | ), 47 | InkWell( 48 | onTap: homeController.onEditProfileClick, 49 | child: const Icon(Icons.edit), 50 | ) 51 | ], 52 | ), 53 | SizedBox(height: 4.w), 54 | const CustomRowTextWidget( 55 | title: '${Strings.mobile}: ', 56 | subtitle: '+91123456789', 57 | ), 58 | ], 59 | ), 60 | ), 61 | ), 62 | ], 63 | ), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_drawer_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/modules/home/controllers/home_controller.dart'; 4 | import 'package:flutter_getx_template/app/modules/widgets/custom_drawer_header.dart'; 5 | import 'package:flutter_getx_template/app/modules/widgets/custom_listtile_widget.dart'; 6 | 7 | class CustomDrawerWidget extends StatelessWidget { 8 | final HomeController controller; 9 | 10 | const CustomDrawerWidget({ 11 | Key? key, 12 | required this.controller, 13 | }) : super(key: key); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return SafeArea( 18 | child: Drawer( 19 | child: Column( 20 | crossAxisAlignment: CrossAxisAlignment.start, 21 | children: [ 22 | CustomDrawerHeader( 23 | homeController: controller, 24 | ), 25 | Padding( 26 | padding: EdgeInsets.symmetric(horizontal: 15.w), 27 | child: Divider( 28 | thickness: 2.w, 29 | color: AppColors.doveGray.withOpacity(0.5), 30 | ), 31 | ), 32 | Expanded( 33 | child: ListView( 34 | padding: EdgeInsets.zero, 35 | children: [ 36 | CustomListTileWidget( 37 | title: Strings.gallery, 38 | onTap: controller.onFaqsClick, 39 | ), 40 | ], 41 | ), 42 | ), 43 | CustomListTileWidget( 44 | title: Strings.logOut, 45 | onTap: controller.onLogoutClick, 46 | ), 47 | ], 48 | ), 49 | ), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_dropdown_textfield.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/common/util/validators.dart'; 4 | 5 | class CustomDropdownTextField extends StatelessWidget { 6 | final String title; 7 | final ValueChanged onChanged; 8 | final FormFieldSetter? onSaved; 9 | final List dataList; 10 | final String Function(T data)? item; 11 | final double? width; 12 | final T? value; 13 | final double? textFontSize; 14 | 15 | const CustomDropdownTextField({ 16 | Key? key, 17 | required this.title, 18 | required this.dataList, 19 | required this.item, 20 | required this.onChanged, 21 | this.onSaved, 22 | this.width, 23 | this.value, 24 | this.textFontSize, 25 | }) : super(key: key); 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return dataList.isNotEmpty 30 | ? SizedBox( 31 | width: width?.w, 32 | child: DropdownButtonFormField( 33 | isExpanded: true, 34 | icon: const Icon(Icons.arrow_drop_down), 35 | value: value, 36 | decoration: InputDecoration( 37 | filled: true, 38 | hintText: value == null ? '' : item!(value!), 39 | labelText: title, 40 | hintStyle: AppTextStyle.regularStyle.copyWith( 41 | fontSize: textFontSize ?? Dimens.fontSize14, 42 | color: AppColors.mineShaft, 43 | ), 44 | floatingLabelBehavior: value == null || item == null 45 | ? FloatingLabelBehavior.never 46 | : FloatingLabelBehavior.always, 47 | fillColor: Colors.white, 48 | contentPadding: EdgeInsets.symmetric(horizontal: 12.w), 49 | ), 50 | autovalidateMode: AutovalidateMode.onUserInteraction, 51 | validator: Validators.validateTEmpty, 52 | onChanged: onChanged, 53 | onSaved: onSaved, 54 | items: dataList 55 | .map>( 56 | (e) => DropdownMenuItem( 57 | value: e, 58 | child: Text( 59 | item!(e), 60 | maxLines: 1, 61 | overflow: TextOverflow.ellipsis, 62 | style: AppTextStyle.regularStyle.copyWith( 63 | fontSize: textFontSize ?? Dimens.fontSize14, 64 | color: AppColors.mineShaft, 65 | ), 66 | ), 67 | ), 68 | ) 69 | .toList(), 70 | ), 71 | ) 72 | : const SizedBox.shrink(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_elevated_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomElevatedButton extends StatelessWidget { 5 | final String? title; 6 | final VoidCallback onPressed; 7 | final TextStyle? textStyle; 8 | final double height, minWidth; 9 | final Widget? titleWidget; 10 | final Color buttonColor; 11 | final bool addBorder; 12 | 13 | const CustomElevatedButton({ 14 | Key? key, 15 | this.title, 16 | required this.onPressed, 17 | this.textStyle, 18 | this.height = 52, 19 | this.minWidth = 100, 20 | this.buttonColor = AppColors.kPrimaryColor, 21 | this.titleWidget, 22 | this.addBorder = false, 23 | }) : assert( 24 | title == null || titleWidget == null, 25 | 'Cannot provide both a title and a child\n' 26 | 'To provide both, use "titleWidget: Text(title)".', 27 | ), 28 | super(key: key); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return ElevatedButton( 33 | onPressed: onPressed, 34 | style: ButtonStyle( 35 | minimumSize: MaterialStateProperty.resolveWith( 36 | (states) => Size( 37 | minWidth.w, 38 | height.h, 39 | ), 40 | ), 41 | shape: addBorder 42 | ? MaterialStateProperty.resolveWith( 43 | (states) => RoundedRectangleBorder( 44 | borderRadius: 10.borderRadius, 45 | side: BorderSide( 46 | color: buttonColor == AppColors.kPrimaryColor 47 | ? Colors.white 48 | : AppColors.kPrimaryColor, 49 | width: 2.w, 50 | ), 51 | ), 52 | ) 53 | : AppTheme.theme.textButtonTheme.style!.shape, 54 | overlayColor: MaterialStateProperty.resolveWith( 55 | (Set states) { 56 | if (states.contains(MaterialState.pressed)) { 57 | return buttonColor == Colors.transparent || 58 | buttonColor == Colors.white 59 | ? AppColors.kPrimaryColor.withOpacity(.24) 60 | : Colors.white.withOpacity(.14); 61 | } 62 | 63 | return null; 64 | }, 65 | ), 66 | backgroundColor: MaterialStateProperty.resolveWith( 67 | (Set states) { 68 | if (states.contains(MaterialState.disabled)) { 69 | return AppColors.doveGray; 70 | } 71 | return buttonColor; 72 | }, 73 | ), 74 | ), 75 | child: titleWidget ?? 76 | Text( 77 | title!, 78 | style: textStyle ?? 79 | AppTextStyle.boldStyle.copyWith( 80 | fontSize: Dimens.fontSize14, 81 | color: buttonColor == Colors.white || 82 | buttonColor == Colors.transparent 83 | ? AppColors.kPrimaryColor 84 | : Colors.white, 85 | ), 86 | ), 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_error_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | class CustomErrorWidget extends StatelessWidget { 6 | final String? message; 7 | 8 | const CustomErrorWidget({ 9 | Key? key, 10 | this.message, 11 | }) : super(key: key); 12 | 13 | @override 14 | Widget build(BuildContext context) { 15 | return Scaffold( 16 | body: Center( 17 | child: Text( 18 | message ?? Strings.somethingWentWrong, 19 | style: Get.textTheme.headline5, 20 | ), 21 | ), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_image_widget.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_getx_template/app/common/constants.dart'; 5 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 6 | import 'package:get/get.dart'; 7 | import 'package:octo_image/octo_image.dart'; 8 | 9 | class CustomImageWidget extends StatelessWidget { 10 | final String? imageUrl; 11 | final Size? size; 12 | final double? height, radius; 13 | final BorderRadius? borderRadius; 14 | final Color? color; 15 | 16 | const CustomImageWidget({ 17 | Key? key, 18 | required this.imageUrl, 19 | this.size, 20 | this.radius, 21 | this.borderRadius, 22 | this.color, 23 | this.height, 24 | }) : assert( 25 | borderRadius == null || radius == null, 26 | 'Cannot provide both a borderRadius and a radius\n', 27 | ), 28 | super(key: key); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return (radius != null || borderRadius != null) 33 | ? ClipRRect( 34 | borderRadius: borderRadius ?? radius?.borderRadius, 35 | child: child, 36 | ) 37 | : child; 38 | } 39 | 40 | Widget get child => 41 | imageUrl == null || (imageUrl != null && imageUrl!.isEmpty) 42 | ? placeholder 43 | : (GetUtils.isURL(imageUrl ?? Constants.dummyImageUrl) || 44 | imageUrl!.startsWith('https') || 45 | imageUrl!.startsWith('http') 46 | ? OctoImage( 47 | image: NetworkImage( 48 | imageUrl ?? Constants.dummyImageUrl, 49 | ), 50 | placeholderBuilder: OctoPlaceholder.blurHash( 51 | Constants.placeHolderBlurHash, 52 | ), 53 | errorBuilder: (context, error, stackTrace) { 54 | return placeholder; 55 | }, 56 | fit: BoxFit.cover, 57 | width: size?.width.w, 58 | height: height?.w ?? size?.height.w, 59 | color: color, 60 | ) 61 | : (File(imageUrl!).existsSync() 62 | ? Image.file( 63 | File(imageUrl!), 64 | width: size?.width.w, 65 | height: height?.w ?? size?.height.w, 66 | fit: BoxFit.cover, 67 | ) 68 | : placeholder)); 69 | 70 | Widget get placeholder => Icon( 71 | Icons.error, 72 | size: size?.width.w, 73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_inkwell_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | class CustomInkwellWidget extends Material { 6 | CustomInkwellWidget({ 7 | Key? key, 8 | required Function() onTap, 9 | required Widget child, 10 | }) : super( 11 | key: key, 12 | color: Colors.transparent, 13 | child: InkWell( 14 | onTap: onTap, 15 | splashColor: AppColors.kPrimaryColor.withOpacity(0.24), 16 | child: child.paddingAll(8), 17 | ), 18 | ); 19 | 20 | CustomInkwellWidget.text({ 21 | Key? key, 22 | required Function() onTap, 23 | required String title, 24 | TextStyle? textStyle, 25 | Color? textColor, 26 | double? textSize, 27 | }) : assert( 28 | textColor == null || textStyle == null, 29 | 'Cannot provide both a textColor and a textStyle\n' 30 | 'To provide both, use "textStyle: TextStyle(color: color)".', 31 | ), 32 | assert( 33 | textSize == null || textStyle == null, 34 | 'Cannot provide both a textSize and a textStyle\n' 35 | 'To provide both, use "textStyle: TextStyle(size: textSize)".', 36 | ), 37 | super( 38 | key: key, 39 | color: Colors.transparent, 40 | child: InkWell( 41 | onTap: onTap, 42 | child: Text( 43 | title, 44 | style: textStyle ?? 45 | AppTextStyle.regularStyle.copyWith( 46 | color: textColor, 47 | fontSize: textSize, 48 | ), 49 | ).paddingAll(8), 50 | ), 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_listtile_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomListTileWidget extends StatelessWidget { 5 | final String title; 6 | final Function() onTap; 7 | final Widget? trailing; 8 | 9 | const CustomListTileWidget({ 10 | Key? key, 11 | required this.title, 12 | required this.onTap, 13 | this.trailing, 14 | }) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return ListTile( 19 | onTap: onTap, 20 | title: Text( 21 | title, 22 | style: AppTextStyle.semiBoldStyle.copyWith( 23 | color: AppColors.black, 24 | fontSize: Dimens.fontSize16, 25 | ), 26 | ), 27 | trailing: trailing ?? const Icon(Icons.arrow_forward_ios_sharp), 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_on_board_card_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomOnBoardCardWidget extends StatelessWidget { 5 | final String title, subtitle; 6 | final double? titleTextSize, subtitleTextSize; 7 | final List children; 8 | 9 | const CustomOnBoardCardWidget({ 10 | Key? key, 11 | required this.children, 12 | required this.title, 13 | required this.subtitle, 14 | this.titleTextSize, 15 | this.subtitleTextSize, 16 | }) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Center( 21 | child: Container( 22 | margin: const EdgeInsets.all(10), 23 | decoration: BoxDecoration( 24 | color: Colors.white.withOpacity(0.85), 25 | borderRadius: 10.borderRadius, 26 | ), 27 | child: SingleChildScrollView( 28 | padding: const EdgeInsets.all(10), 29 | child: Column( 30 | mainAxisSize: MainAxisSize.min, 31 | crossAxisAlignment: CrossAxisAlignment.stretch, 32 | children: [ 33 | Text( 34 | title, 35 | style: AppTextStyle.semiBoldStyle.copyWith( 36 | color: Colors.black, 37 | fontSize: titleTextSize ?? Dimens.fontSize28, 38 | ), 39 | ), 40 | SizedBox(height: 5.h), 41 | Text( 42 | subtitle, 43 | style: AppTextStyle.regularStyle.copyWith( 44 | color: AppColors.mineShaft.withOpacity(0.65), 45 | fontSize: subtitleTextSize ?? Dimens.fontSize16, 46 | ), 47 | ), 48 | SizedBox(height: 22.h), 49 | ...children, 50 | ], 51 | ), 52 | ), 53 | ), 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_password_field.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | import 'package:flutter_getx_template/app/common/util/validators.dart'; 4 | 5 | class PasswordFieldWidget extends StatelessWidget { 6 | final String? title, initialValue; 7 | final TextEditingController? controller; 8 | final bool obscureText; 9 | final Function() onObscureIconClick; 10 | final ValueChanged? onChanged, onSaved; 11 | final Widget? prefixIcon; 12 | final FormFieldValidator validator; 13 | final TextInputAction textInputAction; 14 | 15 | const PasswordFieldWidget({ 16 | Key? key, 17 | this.controller, 18 | required this.obscureText, 19 | required this.onObscureIconClick, 20 | this.title, 21 | this.onChanged, 22 | this.onSaved, 23 | this.initialValue, 24 | this.validator = Validators.validatePassword, 25 | this.textInputAction = TextInputAction.next, 26 | this.prefixIcon, 27 | }) : super(key: key); 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return TextFormField( 32 | initialValue: initialValue, 33 | autovalidateMode: AutovalidateMode.onUserInteraction, 34 | obscureText: obscureText, 35 | textInputAction: textInputAction, 36 | validator: validator, 37 | onChanged: onChanged, 38 | onSaved: onSaved, 39 | decoration: InputDecoration( 40 | labelText: title ?? Strings.password, 41 | prefixIcon: prefixIcon, 42 | suffixIcon: IconButton( 43 | onPressed: onObscureIconClick, 44 | color: AppColors.kPrimaryColor, 45 | icon: Icon( 46 | obscureText ? Icons.visibility_off : Icons.visibility, 47 | size: 20.w, 48 | ), 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_retry_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | import 'custom_text_button.dart'; 5 | 6 | class CustomRetryWidget extends StatelessWidget { 7 | final String error; 8 | final VoidCallback onPressed; 9 | 10 | const CustomRetryWidget({ 11 | Key? key, 12 | required this.onPressed, 13 | this.error = Strings.somethingWentWrong, 14 | }) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return Center( 19 | child: Column( 20 | mainAxisAlignment: MainAxisAlignment.center, 21 | mainAxisSize: MainAxisSize.min, 22 | children: [ 23 | Text(error), 24 | SizedBox(height: 16.h), 25 | CustomTextButton( 26 | buttonWidth: 85.w, 27 | height: 45, 28 | onPressed: onPressed, 29 | title: Strings.retry, 30 | ), 31 | ], 32 | ), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_rich_text_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomRichTextWidget extends StatelessWidget { 5 | final String title, subtitle; 6 | final TextStyle? titleStyle, subtitleStyle; 7 | final TextAlign textAlign; 8 | 9 | const CustomRichTextWidget({ 10 | Key? key, 11 | required this.title, 12 | required this.subtitle, 13 | this.titleStyle, 14 | this.subtitleStyle, 15 | this.textAlign = TextAlign.center, 16 | }) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return RichText( 21 | textAlign: textAlign, 22 | text: TextSpan( 23 | text: title, 24 | style: titleStyle ?? 25 | AppTextStyle.regularStyle.copyWith( 26 | color: AppColors.mineShaft, 27 | fontSize: Dimens.fontSize14, 28 | ), 29 | children: [ 30 | TextSpan( 31 | text: ' $subtitle', 32 | style: subtitleStyle ?? 33 | AppTextStyle.regularStyle.copyWith( 34 | fontSize: Dimens.fontSize14, 35 | ), 36 | ), 37 | ], 38 | ), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_row_text_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomRowTextWidget extends StatelessWidget { 5 | final String title, subtitle; 6 | final TextStyle? titleStyle, subtitleStyle; 7 | final MainAxisAlignment mainAxisAlignment; 8 | 9 | const CustomRowTextWidget({ 10 | Key? key, 11 | required this.title, 12 | required this.subtitle, 13 | this.titleStyle, 14 | this.subtitleStyle, 15 | this.mainAxisAlignment = MainAxisAlignment.spaceBetween, 16 | }) : super(key: key); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Row( 21 | crossAxisAlignment: CrossAxisAlignment.start, 22 | mainAxisAlignment: mainAxisAlignment, 23 | children: [ 24 | Text( 25 | title, 26 | maxLines: 1, 27 | style: titleStyle ?? 28 | AppTextStyle.regularStyle.copyWith( 29 | color: AppColors.mineShaft, 30 | ), 31 | ), 32 | Text( 33 | subtitle, 34 | maxLines: 1, 35 | overflow: TextOverflow.ellipsis, 36 | style: subtitleStyle ?? 37 | AppTextStyle.regularStyle.copyWith( 38 | color: Colors.black, 39 | ), 40 | ), 41 | ], 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_text_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class CustomTextButton extends StatelessWidget { 5 | final VoidCallback onPressed; 6 | final String? title; 7 | final double height; 8 | final double? buttonWidth, textFontSize; 9 | final Widget? child; 10 | final Color buttonColor; 11 | final bool addBorder; 12 | 13 | const CustomTextButton({ 14 | Key? key, 15 | required this.onPressed, 16 | this.title, 17 | this.height = 52, 18 | this.child, 19 | this.buttonColor = AppColors.kPrimaryColor, 20 | this.buttonWidth, 21 | this.textFontSize, 22 | this.addBorder = false, 23 | }) : assert( 24 | title == null || child == null, 25 | 'Cannot provide both a title and a child\n' 26 | 'To provide both, use "child: Text(title)".', 27 | ), 28 | super(key: key); 29 | 30 | @override 31 | Widget build(BuildContext context) { 32 | return TextButton( 33 | onPressed: onPressed, 34 | style: AppTheme.theme.textButtonTheme.style!.copyWith( 35 | minimumSize: MaterialStateProperty.resolveWith( 36 | (states) => buttonWidth == null 37 | ? Size.fromHeight(height.h) 38 | : Size( 39 | buttonWidth!, 40 | height.h, 41 | ), 42 | ), 43 | overlayColor: MaterialStateProperty.resolveWith( 44 | (Set states) { 45 | if (states.contains(MaterialState.pressed)) { 46 | return buttonColor == Colors.transparent || 47 | buttonColor == Colors.white 48 | ? AppColors.kPrimaryColor.withOpacity(.24) 49 | : Colors.white.withOpacity(.14); 50 | } 51 | 52 | return null; 53 | }, 54 | ), 55 | shape: addBorder 56 | ? MaterialStateProperty.resolveWith( 57 | (states) => RoundedRectangleBorder( 58 | borderRadius: 23.borderRadius, 59 | side: BorderSide( 60 | color: buttonColor == AppColors.kPrimaryColor 61 | ? Colors.white 62 | : AppColors.kPrimaryColor, 63 | width: 2.w, 64 | ), 65 | ), 66 | ) 67 | : AppTheme.theme.textButtonTheme.style!.shape, 68 | backgroundColor: MaterialStateProperty.resolveWith( 69 | (Set states) { 70 | if (states.contains(MaterialState.disabled)) { 71 | return AppColors.doveGray; 72 | } 73 | 74 | return buttonColor; 75 | }, 76 | ), 77 | ), 78 | child: child ?? 79 | Text( 80 | title!, 81 | style: AppTextStyle.buttonTextStyle.copyWith( 82 | fontSize: textFontSize ?? Dimens.fontSize16, 83 | color: buttonColor == Colors.white || 84 | buttonColor == Colors.transparent 85 | ? AppColors.kPrimaryColor 86 | : Colors.white, 87 | ), 88 | ), 89 | ); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/custom_text_field_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 4 | import 'package:flutter_getx_template/app/common/util/validators.dart'; 5 | 6 | class CustomTextFieldWidget extends StatelessWidget { 7 | final String? labelText, hintText; 8 | final String? initialValue, prefixText, suffixText; 9 | final Widget? prefixIcon, suffixIcon; 10 | final TextInputType keyboardType; 11 | final FormFieldValidator? validator; 12 | final TextEditingController? controller; 13 | final ValueChanged? onChanged, onSaved; 14 | final int? maxLength, maxLines; 15 | final int minLines; 16 | final bool readOnly, addHint, enabled; 17 | final bool? isDense; 18 | final Function()? onTap; 19 | final InputBorder? border; 20 | final AutovalidateMode autovalidateMode; 21 | final BoxConstraints? suffixIconConstraints; 22 | final EdgeInsets? prefixIconPadding; 23 | final Color? fillColor; 24 | 25 | const CustomTextFieldWidget({ 26 | Key? key, 27 | this.labelText, 28 | this.hintText, 29 | this.controller, 30 | this.prefixIcon, 31 | this.suffixIcon, 32 | this.keyboardType = TextInputType.text, 33 | this.validator = Validators.validateEmpty, 34 | this.onChanged, 35 | this.onSaved, 36 | this.maxLength, 37 | this.maxLines, 38 | this.minLines = 1, 39 | this.initialValue, 40 | this.readOnly = false, 41 | this.onTap, 42 | this.border, 43 | this.enabled = true, 44 | this.autovalidateMode = AutovalidateMode.onUserInteraction, 45 | this.addHint = false, 46 | this.suffixIconConstraints, 47 | this.prefixText, 48 | this.suffixText, 49 | this.isDense, 50 | this.prefixIconPadding, 51 | this.fillColor, 52 | }) : super(key: key); 53 | 54 | @override 55 | Widget build(BuildContext context) { 56 | final textStyle = AppTextStyle.regularStyle.copyWith( 57 | color: AppColors.mineShaft, 58 | fontSize: Dimens.fontSize15, 59 | ); 60 | 61 | return TextFormField( 62 | onTap: onTap, 63 | readOnly: readOnly, 64 | initialValue: initialValue, 65 | keyboardType: keyboardType, 66 | autovalidateMode: autovalidateMode, 67 | controller: controller, 68 | validator: validator, 69 | onChanged: onChanged, 70 | minLines: minLines, 71 | maxLines: maxLines, 72 | onSaved: onSaved, 73 | enabled: enabled, 74 | inputFormatters: maxLength == null 75 | ? null 76 | : [ 77 | LengthLimitingTextInputFormatter(maxLength), 78 | if (keyboardType == TextInputType.number) 79 | FilteringTextInputFormatter.digitsOnly, 80 | ], 81 | decoration: InputDecoration( 82 | fillColor: fillColor, 83 | filled: fillColor != null, 84 | isDense: isDense, 85 | border: border, 86 | enabledBorder: border, 87 | focusedBorder: border, 88 | // alignLabelWithHint: maxLines == null, 89 | labelText: addHint 90 | ? null 91 | : ((controller?.text != null || !readOnly) ? labelText : null), 92 | hintText: hintText, 93 | prefixIconConstraints: BoxConstraints( 94 | maxHeight: 40.h, 95 | maxWidth: 40.w, 96 | ), 97 | prefixIcon: prefixIcon == null 98 | ? null 99 | : Padding( 100 | padding: prefixIconPadding ?? EdgeInsets.only(right: 10.w), 101 | child: prefixIcon, 102 | ), 103 | prefixText: prefixText, 104 | suffixText: suffixText, 105 | prefixStyle: textStyle, 106 | suffixStyle: textStyle, 107 | suffixIcon: suffixIcon == null 108 | ? null 109 | : Padding( 110 | padding: EdgeInsets.symmetric(horizontal: 10.w), 111 | child: suffixIcon, 112 | ), 113 | suffixIconConstraints: suffixIconConstraints ?? 114 | BoxConstraints( 115 | maxHeight: 40.h, 116 | maxWidth: 40.w, 117 | ), 118 | ), 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/on_boarding_base_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/data/interface_controller/api_interface_controller.dart'; 3 | import 'package:flutter_getx_template/app/modules/widgets/custom_retry_widget.dart'; 4 | import 'package:get/get.dart'; 5 | 6 | export 'package:flutter_getx_template/app/common/util/exports.dart'; 7 | 8 | class OnBoardingBaseWidget extends GetView { 9 | ///A widget with custom background and custom retry button widget. 10 | ///You've to add "backgroundColor: Colors.transparent" in Scaffold 11 | ///in order to see backgroundImage properly. 12 | 13 | final Widget child; 14 | final Color? backgroundColor; 15 | final bool addBackgroundImage; 16 | final Alignment alignment; 17 | 18 | const OnBoardingBaseWidget({ 19 | Key? key, 20 | required this.child, 21 | this.backgroundColor, 22 | this.addBackgroundImage = false, 23 | this.alignment = Alignment.center, 24 | }) : super(key: key); 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Obx( 29 | () => controller.error != null 30 | ? SafeArea( 31 | child: CustomRetryWidget( 32 | onPressed: () { 33 | controller.error = null; 34 | if (controller.retry != null) { 35 | controller.retry!(); 36 | } 37 | }, 38 | ), 39 | ) 40 | : Container( 41 | height: Get.height, 42 | alignment: alignment, 43 | decoration: BoxDecoration( 44 | color: (!addBackgroundImage && backgroundColor == null) 45 | ? Colors.white 46 | : backgroundColor, 47 | // image: !addBackgroundImage 48 | // ? null 49 | // : DecorationImage( 50 | // fit: BoxFit.cover, 51 | // image: AssetImage(AppImages.backgroundImage), 52 | // ), 53 | // 54 | //add background here 55 | ), 56 | child: SafeArea( 57 | child: child, 58 | ), 59 | ), 60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/app/modules/widgets/stroke_background.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/exports.dart'; 3 | 4 | class StrokeBackground extends StatelessWidget { 5 | final Widget child; 6 | final Function() onTap; 7 | final double? height; 8 | 9 | const StrokeBackground({ 10 | Key? key, 11 | required this.onTap, 12 | required this.child, 13 | this.height, 14 | }) : super(key: key); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return InkWell( 19 | borderRadius: 10.borderRadius, 20 | onTap: onTap, 21 | child: Container( 22 | height: height?.h, 23 | padding: EdgeInsets.symmetric( 24 | horizontal: 10.w, 25 | vertical: 10.h, 26 | ), 27 | decoration: BoxDecoration( 28 | borderRadius: 10.borderRadius, 29 | border: Border.all( 30 | color: Colors.grey[200]!, 31 | width: 3.w, 32 | ), 33 | ), 34 | child: child, 35 | ), 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/app/routes/app_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_getx_template/app/modules/home/bindings/home_binding.dart'; 2 | import 'package:flutter_getx_template/app/modules/home/views/home_view.dart'; 3 | import 'package:get/get.dart'; 4 | 5 | part 'app_routes.dart'; 6 | 7 | abstract class AppPages { 8 | const AppPages._(); 9 | 10 | static const INITIAL = Routes.HOME; 11 | 12 | static final routes = [ 13 | GetPage( 14 | name: _Paths.HOME, 15 | page: () => const HomeView(), 16 | binding: HomeBinding(), 17 | ), 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /lib/app/routes/app_routes.dart: -------------------------------------------------------------------------------- 1 | part of 'app_pages.dart'; 2 | // DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart 3 | 4 | abstract class Routes { 5 | static const HOME = _Paths.HOME; 6 | } 7 | 8 | abstract class _Paths { 9 | static const HOME = '/home'; 10 | } 11 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_getx_template/app/common/util/initializer.dart'; 3 | import 'package:flutter_getx_template/app/routes/app_pages.dart'; 4 | import 'package:get/get.dart'; 5 | 6 | import 'app/modules/widgets/base_widget.dart'; 7 | 8 | void main() { 9 | Initializer.init(() { 10 | runApp(const MyApp()); 11 | }); 12 | } 13 | 14 | class MyApp extends StatelessWidget { 15 | const MyApp({Key? key}) : super(key: key); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return ScreenUtilInit( 20 | builder: () => GetMaterialApp( 21 | title: Strings.appName, 22 | debugShowCheckedModeBanner: false, 23 | theme: AppTheme.theme, 24 | initialRoute: AppPages.INITIAL, 25 | getPages: AppPages.routes, 26 | initialBinding: InitialBindings(), 27 | builder: (_, child) => BaseWidget( 28 | child: child ?? const SizedBox.shrink(), 29 | ), 30 | ), 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_getx_template 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: "none" # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.12.0 <3.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | cupertino_icons: ^1.0.0 27 | 28 | #for dynamic ui 29 | flutter_screenutil: ^5.3.1 30 | 31 | #for state management 32 | get: ^4.6.1 33 | get_storage: ^2.0.3 34 | 35 | image_picker: ^0.8.5 36 | image_cropper: ^1.5.1 37 | 38 | #for date formatting 39 | intl: ^0.17.0 40 | 41 | octo_image: ^1.0.1 42 | 43 | dev_dependencies: 44 | flutter_test: 45 | sdk: flutter 46 | 47 | flutter_lints: ^1.0.0 48 | 49 | # For information on the generic Dart part of this file, see the 50 | # following page: https://dart.dev/tools/pub/pubspec 51 | # The following section is specific to Flutter. 52 | flutter: 53 | # The following line ensures that the Material Icons font is 54 | # included with your application, so that you can use the icons in 55 | # the material Icons class. 56 | uses-material-design: true 57 | # To add assets to your application, add an assets section, like this: 58 | assets: 59 | - assets/images/ 60 | # - images/a_dot_ham.jpeg 61 | # An image asset can refer to one or more resolution-specific "variants", see 62 | # https://flutter.dev/assets-and-images/#resolution-aware. 63 | # For details regarding adding assets from package dependencies, see 64 | # https://flutter.dev/assets-and-images/#from-packages 65 | # To add custom fonts to your application, add a fonts section here, 66 | # in this "flutter" section. Each entry in this list should have a 67 | # "family" key with the font family name, and a "fonts" key with a 68 | # list giving the asset and other descriptors for the font. For 69 | # example: 70 | # fonts: 71 | # - family: Schyler 72 | # fonts: 73 | # - asset: fonts/Schyler-Regular.ttf 74 | # - asset: fonts/Schyler-Italic.ttf 75 | # style: italic 76 | # - family: Trajan Pro 77 | # fonts: 78 | # - asset: fonts/TrajanPro.ttf 79 | # - asset: fonts/TrajanPro_Bold.ttf 80 | # weight: 700 81 | # 82 | # For details regarding fonts from package dependencies, 83 | # see https://flutter.dev/custom-fonts/#from-packages 84 | --------------------------------------------------------------------------------