├── ios
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── 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-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ ├── xcshareddata
│ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ └── project.pbxproj
└── .gitignore
├── lib
├── Models
│ ├── index.dart
│ ├── BaseModel.dart
│ └── ListViewItem.dart
├── Layouts
│ ├── index.dart
│ ├── DefaultAppbarLayout.dart
│ └── ListViewLayout.dart
├── Screens
│ ├── index.dart
│ ├── GetxNavigation
│ │ ├── ScreenFour.dart
│ │ ├── ScreenFive.dart
│ │ ├── ScreenTwo.dart
│ │ ├── ScreenThree.dart
│ │ └── GetxNavigationScreen.dart
│ ├── ProviderOptimisticResponse
│ │ ├── PostModel.dart
│ │ ├── ProviderOptimisticResponseScreen.dart
│ │ ├── PostCard.dart
│ │ └── PostProvider.dart
│ ├── Retrofit
│ │ ├── Retrofit
│ │ │ ├── RestClient.dart
│ │ │ └── RestClient.g.dart
│ │ └── Screens
│ │ │ └── RetrofitScreen.dart
│ ├── ProviderInfiniteScroll
│ │ ├── AjaxProvider.dart
│ │ └── ProviderInfiniteScrollScreen.dart
│ ├── CustomKeyboard
│ │ ├── KeyboardKey.dart
│ │ └── CustomKeyboard.dart
│ ├── CustomPaintHermesAppleWatch
│ │ ├── CustomPaintHermesAppleWatch.dart
│ │ └── WatchPainter.dart
│ ├── GetxStateManagement
│ │ ├── OnUpdateScreen.dart
│ │ ├── GetxStateManagement.dart
│ │ ├── GetxController.dart
│ │ └── ReactiveScreen.dart
│ ├── Home
│ │ └── HomeScreen.dart
│ ├── CustomScrollView
│ │ └── CustomScrollViewScreen.dart
│ └── RowAndColumn
│ │ └── RowAndColumn.dart
├── Configs
│ └── Theme.dart
└── main.dart
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── 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
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── codefactory_youtube_flutter_tutorial
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── assets
├── seoul-night-view.jpg
└── flutter-logo-white.png
├── .metadata
├── README.md
├── .gitignore
├── test
└── widget_test.dart
├── pubspec.yaml
└── pubspec.lock
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/Models/index.dart:
--------------------------------------------------------------------------------
1 | export 'BaseModel.dart';
2 | export 'ListViewItem.dart';
3 |
--------------------------------------------------------------------------------
/lib/Layouts/index.dart:
--------------------------------------------------------------------------------
1 | export 'ListViewLayout.dart';
2 | export 'DefaultAppbarLayout.dart';
3 |
--------------------------------------------------------------------------------
/lib/Models/BaseModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | abstract class BaseModel{}
4 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/assets/seoul-night-view.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/assets/seoul-night-view.jpg
--------------------------------------------------------------------------------
/assets/flutter-logo-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/assets/flutter-logo-white.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/Screens/index.dart:
--------------------------------------------------------------------------------
1 | export 'Home/HomeScreen.dart';
2 | export 'RowAndColumn/RowAndColumn.dart';
3 | export 'ProviderOptimisticResponse/ProviderOptimisticResponseScreen.dart';
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/Configs/Theme.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class _Theme {
4 | final Color greyBorderColor = Colors.grey[200];
5 | }
6 |
7 | _Theme THEME = _Theme();
8 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/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/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/serendipity1004/Youtube-Flutter-Tutorials/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/example/codefactory_youtube_flutter_tutorial/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.example.codefactory_youtube_flutter_tutorial
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/Models/ListViewItem.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'index.dart';
3 |
4 | class ListViewItem extends BaseModel {
5 | final String name;
6 | final Widget page;
7 |
8 | ListViewItem({
9 | @required String name,
10 | @required Widget page,
11 | }) : this.name = name,
12 | this.page = page;
13 | }
14 |
--------------------------------------------------------------------------------
/.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: 1aafb3a8b9b0c36241c5f5b34ee914770f015818
8 | channel: stable
9 |
10 | project_type: app
11 |
--------------------------------------------------------------------------------
/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.
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # codefactory_youtube_flutter_tutorial
2 |
3 | A new Flutter project.
4 |
5 | ## Getting Started
6 |
7 | This project is a starting point for a Flutter application.
8 |
9 | A few resources to get you started if this is your first Flutter project:
10 |
11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
13 |
14 | For help getting started with Flutter, view our
15 | [online documentation](https://flutter.dev/docs), which offers tutorials,
16 | samples, guidance on mobile development, and a full API reference.
17 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.50'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.0'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/lib/Layouts/DefaultAppbarLayout.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class DefaultAppbarLayout extends StatefulWidget {
4 | final String title;
5 | final Widget child;
6 |
7 | DefaultAppbarLayout({
8 | @required Widget child,
9 | String title,
10 | }) : this.title = title ?? '코드팩토리',
11 | this.child = child;
12 |
13 | @override
14 | _DefaultAppbarLayoutState createState() => _DefaultAppbarLayoutState();
15 | }
16 |
17 | class _DefaultAppbarLayoutState extends State {
18 | @override
19 | Widget build(BuildContext context) {
20 | return Scaffold(
21 | appBar: AppBar(
22 | title: Text(
23 | widget.title,
24 | ),
25 | ),
26 | body: widget.child,
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/Screens/GetxNavigation/ScreenFour.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class ScreenFour extends StatefulWidget {
6 | @override
7 | _ScreenFourState createState() => _ScreenFourState();
8 | }
9 |
10 | class _ScreenFourState extends State {
11 | @override
12 | Widget build(BuildContext context) {
13 | return DefaultAppbarLayout(
14 | child: Center(
15 | child: Column(
16 | mainAxisAlignment: MainAxisAlignment.center,
17 | children: [
18 | Text(
19 | Get.arguments,
20 | ),
21 | ],
22 | ),
23 | ),
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 |
12 | # IntelliJ related
13 | *.iml
14 | *.ipr
15 | *.iws
16 | .idea/
17 |
18 | # The .vscode folder contains launch configuration and tasks you configure in
19 | # VS Code which you may wish to be included in version control, so this line
20 | # is commented out by default.
21 | #.vscode/
22 |
23 | # Flutter/Dart/Pub related
24 | **/doc/api/
25 | **/ios/Flutter/.last_build_id
26 | .dart_tool/
27 | .flutter-plugins
28 | .flutter-plugins-dependencies
29 | .packages
30 | .pub-cache/
31 | .pub/
32 | /build/
33 |
34 | # Web related
35 | lib/generated_plugin_registrant.dart
36 |
37 | # Symbolication related
38 | app.*.symbols
39 |
40 | # Obfuscation related
41 | app.*.map.json
42 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderOptimisticResponse/PostModel.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class PostModel {
4 | final int id;
5 | final String title;
6 | final String content;
7 |
8 | //좋아요
9 | int likes;
10 |
11 | PostModel.fromJson({
12 | @required Map json,
13 | })
14 | : this.id = json['id'],
15 | this.title = json['title'],
16 | this.content = json['content'],
17 | this.likes = json['likes'];
18 |
19 | incrementLike() {
20 | this.likes = this.likes + 1;
21 | }
22 |
23 | // class 인스턴스를 map 으로 변경
24 | toMap() {
25 | return {
26 | 'id': this.id,
27 | 'title': this.title,
28 | 'content': this.content,
29 | 'likes': this.likes,
30 | };
31 | }
32 |
33 | copyWith(){
34 | return PostModel.fromJson(
35 | json: this.toMap(),
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/Screens/Retrofit/Retrofit/RestClient.dart:
--------------------------------------------------------------------------------
1 | import 'package:json_annotation/json_annotation.dart';
2 | import 'package:retrofit/retrofit.dart';
3 | import 'package:dio/dio.dart';
4 |
5 | part 'RestClient.g.dart';
6 |
7 | @RestApi(baseUrl: 'https://hacker-news.firebaseio.com/v0')
8 | abstract class RestClient {
9 | factory RestClient(Dio dio, {String baseUrl}) = _RestClient;
10 |
11 | @GET('/topstories.json')
12 | Future> getTopNews();
13 |
14 | @GET('/item/{id}.json')
15 | Future getNewsDetail({@Path() int id});
16 | }
17 |
18 | @JsonSerializable()
19 | class News {
20 | int id;
21 | String title;
22 | String type;
23 | String url;
24 |
25 | News({
26 | this.id,
27 | this.title,
28 | this.type,
29 | this.url,
30 | });
31 |
32 | factory News.fromJson(Map json) => _$NewsFromJson(json);
33 |
34 | Map toJson() => _$NewsToJson(this);
35 | }
36 |
--------------------------------------------------------------------------------
/lib/Screens/GetxNavigation/ScreenFive.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class ScreenFive extends StatefulWidget {
6 | @override
7 | _ScreenFiveState createState() => _ScreenFiveState();
8 | }
9 |
10 | class _ScreenFiveState extends State {
11 | @override
12 | Widget build(BuildContext context) {
13 | return DefaultAppbarLayout(
14 | title: 'Screen Five',
15 | child: Center(
16 | child: Column(
17 | mainAxisAlignment: MainAxisAlignment.center,
18 | children: [
19 | Text(
20 | Get.parameters['param'],
21 | ),
22 | Text(
23 | Get.parameters['id'],
24 | ),
25 | Text(
26 | Get.parameters['name'],
27 | ),
28 | ],
29 | ),
30 | ),
31 | );
32 | }
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/Screens/GetxNavigation/ScreenTwo.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class ScreenTwo extends StatefulWidget {
6 | @override
7 | _ScreenTwoState createState() => _ScreenTwoState();
8 | }
9 |
10 | class _ScreenTwoState extends State {
11 | @override
12 | Widget build(BuildContext context) {
13 | return DefaultAppbarLayout(
14 | title: 'Screen Two',
15 | child: Center(
16 | child: Column(
17 | mainAxisAlignment: MainAxisAlignment.center,
18 | children: [
19 | Text('Screen Two'),
20 | RaisedButton(
21 | onPressed: () {
22 | // if(Navigator.of(context).canPop()){
23 | // Navigator.of(context).pop();
24 | // }
25 |
26 | Get.back();
27 | },
28 | child: Text(
29 | '뒤로가기',
30 | ),
31 | ),
32 | ],
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderInfiniteScroll/AjaxProvider.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:provider/provider.dart';
3 |
4 | class AjaxProvider extends ChangeNotifier {
5 | List cache = [];
6 |
7 | // 로딩
8 | bool loading = false;
9 | // 아이템이 더 있는지
10 | bool hasMore = true;
11 |
12 | _makeRequest({
13 | @required int nextId,
14 | }) async {
15 | assert(nextId != null);
16 |
17 | await Future.delayed(Duration(seconds: 1));
18 |
19 | // Item 은 nextId 가 99 까지만 있음
20 | if(nextId == 100){
21 | return [];
22 | }
23 |
24 | //nextId 다음의 20개의 값을 리스트로 리턴
25 | return List.generate(20, (index) => nextId + index);
26 | }
27 |
28 | fetchItems({
29 | int nextId,
30 | }) async {
31 | nextId ??= 0;
32 |
33 | loading = true;
34 |
35 | notifyListeners();
36 |
37 | final items = await _makeRequest(nextId: nextId);
38 |
39 | this.cache = [
40 | ...this.cache,
41 | ...items,
42 | ];
43 |
44 | if(items.length == 0){
45 | hasMore = false;
46 | }
47 |
48 | loading = false;
49 |
50 | notifyListeners();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/Screens/CustomKeyboard/KeyboardKey.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class KeyboardKey extends StatefulWidget {
4 | final dynamic label;
5 | final dynamic value;
6 | final ValueSetter onTap;
7 |
8 | KeyboardKey({
9 | @required this.label,
10 | @required this.value,
11 | @required this.onTap,
12 | });
13 |
14 | @override
15 | _KeyboardKeyState createState() => _KeyboardKeyState();
16 | }
17 |
18 | class _KeyboardKeyState extends State {
19 |
20 | renderLabel(){
21 | if(widget.label is Widget){
22 | return widget.label;
23 | }
24 |
25 | return Text(
26 | widget.label,
27 | style: TextStyle(
28 | fontSize: 20.0,
29 | fontWeight: FontWeight.bold,
30 | ),
31 | );
32 | }
33 |
34 | @override
35 | Widget build(BuildContext context) {
36 | return InkWell(
37 | onTap: (){
38 | widget.onTap(widget.value);
39 | },
40 | child: AspectRatio(
41 | aspectRatio: 2, // 넓이 / 높이 = 2
42 | child: Container(
43 | child: Center(
44 | child: renderLabel(),
45 | ),
46 | ),
47 | ),
48 | );
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility that Flutter provides. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:codefactory_youtube_flutter_tutorial/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/lib/Screens/CustomPaintHermesAppleWatch/CustomPaintHermesAppleWatch.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 |
3 | import 'package:flutter/material.dart';
4 |
5 | import 'WatchPainter.dart';
6 |
7 | class CustomPaintHermesAppleWatch extends StatefulWidget {
8 | @override
9 | _CustomPaintHermesAppleWatchState createState() => _CustomPaintHermesAppleWatchState();
10 | }
11 |
12 | class _CustomPaintHermesAppleWatchState extends State {
13 | DateTime now;
14 |
15 | @override
16 | void initState() {
17 | super.initState();
18 |
19 | now = DateTime.now();
20 |
21 | Timer.periodic(Duration(seconds: 1), (timer) {
22 | setState(() {
23 | now = DateTime.now();
24 | });
25 | });
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | return Scaffold(
31 | body: Container(
32 | color: Colors.black,
33 | alignment: Alignment.center,
34 | child: Container(
35 | width: MediaQuery.of(context).size.width /2,
36 | child: AspectRatio(
37 | aspectRatio: 2/3,
38 | child: CustomPaint(
39 | painter: WatchPainter(
40 | now,
41 | ),
42 | ),
43 | ),
44 | ),
45 | ),
46 | );
47 | }
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/lib/Screens/GetxStateManagement/OnUpdateScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxStateManagement/GetxController.dart';
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:get/get.dart';
6 |
7 | class OnUpdateScreen extends StatefulWidget {
8 | @override
9 | _OnUpdateScreenState createState() => _OnUpdateScreenState();
10 | }
11 |
12 | class _OnUpdateScreenState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | final controller = Get.put(BuilderController());
16 |
17 | return DefaultAppbarLayout(
18 | title: 'On Update',
19 | child: Center(
20 | child: Column(
21 | mainAxisAlignment: MainAxisAlignment.center,
22 | children: [
23 | Text(
24 | 'On Update',
25 | ),
26 | GetBuilder(
27 | builder: (_) {
28 | return Text('count : ${_.count}');
29 | },
30 | ),
31 | RaisedButton(
32 | onPressed: (){
33 | controller.increment();
34 | },
35 | child: Text('Count 업!'),
36 | ),
37 | ],
38 | ),
39 | ),
40 | );
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/lib/Screens/GetxStateManagement/GetxStateManagement.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxStateManagement/OnUpdateScreen.dart';
3 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxStateManagement/ReactiveScreen.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:get/get.dart';
7 |
8 | class GetxStateManagementScreen extends StatefulWidget {
9 | @override
10 | _GetxStateManagementScreenState createState() =>
11 | _GetxStateManagementScreenState();
12 | }
13 |
14 | class _GetxStateManagementScreenState extends State {
15 | @override
16 | Widget build(BuildContext context) {
17 | return DefaultAppbarLayout(
18 | title: 'GetX State Management',
19 | child: Center(
20 | child: Column(
21 | mainAxisAlignment: MainAxisAlignment.center,
22 | children: [
23 | RaisedButton(
24 | onPressed: () {
25 | Get.to(OnUpdateScreen());
26 | },
27 | child: Text('On Update'),
28 | ),
29 | RaisedButton(
30 | onPressed: (){
31 | Get.to(ReactiveScreen());
32 | },
33 | child: Text('Reactive'),
34 | ),
35 | ],
36 | ),
37 | ),
38 | );
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/Screens/GetxStateManagement/GetxController.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:get/get.dart';
3 |
4 | class BuilderController extends GetxController {
5 | int count = 0;
6 |
7 | increment() {
8 | count++;
9 | update();
10 | }
11 | }
12 |
13 | class User {
14 | int id;
15 | String name;
16 |
17 | User({
18 | @required int id,
19 | @required String name,
20 | }) : this.id = id,
21 | this.name = name;
22 | }
23 |
24 | class ReactiveController extends GetxController {
25 | RxInt count1 = 0.obs;
26 | var count2 = 0.obs;
27 |
28 | var user = new User(
29 | id: 1,
30 | name: '코드팩토리',
31 | ).obs;
32 |
33 | List testList = [1, 2, 3, 4, 5].obs;
34 |
35 | get sum => count1.value + count2.value;
36 |
37 | change({
38 | @required int id,
39 | @required String name,
40 | }) {
41 | user.update((val) {
42 | val.name = name;
43 | val.id = id;
44 | });
45 | }
46 |
47 | @override
48 | void onInit() {
49 | super.onInit();
50 |
51 | ever(count1, (_) {
52 | print('EVER : COUNT1 이 변경 될때마다 실행');
53 | });
54 | once(count1, (_) {
55 | print('ONCE : 처음으로 COUNT1 이 변경 되었을때');
56 | });
57 | debounce(
58 | count1,
59 | (_) {
60 | print('DEBOUNCE : 1초간 디바운스 한 뒤에 실행');
61 | },
62 | time: Duration(seconds: 1),
63 | );
64 | interval(
65 | count1,
66 | (_) {
67 | print('INTERVAL : 1초간 이터벌이 지나면 실행');
68 | },
69 | time: Duration(seconds: 1),
70 | );
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderOptimisticResponse/ProviderOptimisticResponseScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Screens/ProviderOptimisticResponse/PostCard.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
4 | import 'package:provider/provider.dart';
5 | import 'PostProvider.dart';
6 |
7 | class ProviderOptimisticResponseScreen extends StatefulWidget {
8 | @override
9 | _ProviderOptimisticResponseScreenState createState() =>
10 | _ProviderOptimisticResponseScreenState();
11 | }
12 |
13 | class _ProviderOptimisticResponseScreenState
14 | extends State {
15 | @override
16 | void initState() {
17 | // TODO: implement initState
18 | super.initState();
19 |
20 | Future.microtask(() {
21 | Provider.of(context, listen: false).fetchItems();
22 | });
23 | }
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | final provider = Provider.of(context);
28 | final posts = provider.posts;
29 |
30 | return DefaultAppbarLayout(
31 | title: 'Provider Optimistic Response',
32 | child: ListView.separated(
33 | itemBuilder: (context, index) {
34 | return PostCard(
35 | postId: index,
36 | );
37 | },
38 | separatorBuilder: (context, index) {
39 | return Container(
40 | color: Colors.grey[200],
41 | height: 16.0,
42 | );
43 | },
44 | itemCount: posts.length,
45 | ),
46 | );
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/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 | codefactory_youtube_flutter_tutorial
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 |
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxNavigation/GetxNavigationScreen.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxNavigation/ScreenFive.dart';
3 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxNavigation/ScreenFour.dart';
4 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxNavigation/ScreenThree.dart';
5 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxNavigation/ScreenTwo.dart';
6 | import 'package:codefactory_youtube_flutter_tutorial/Screens/Home/HomeScreen.dart';
7 | import 'package:codefactory_youtube_flutter_tutorial/Screens/ProviderInfiniteScroll/AjaxProvider.dart';
8 | import 'package:codefactory_youtube_flutter_tutorial/Screens/ProviderOptimisticResponse/PostProvider.dart';
9 | import 'package:flutter/material.dart';
10 | import 'package:provider/provider.dart';
11 | import 'package:get/get.dart';
12 |
13 | void main() {
14 | runApp(
15 | MultiProvider(
16 | providers: [
17 | ChangeNotifierProvider(
18 | create: (_) => AjaxProvider(),
19 | ),
20 | ChangeNotifierProvider(
21 | create: (_) => PostProvider(),
22 | ),
23 | ],
24 | child: MyApp(),
25 | ),
26 | );
27 | }
28 |
29 | class MyApp extends StatelessWidget {
30 | @override
31 | Widget build(BuildContext context) {
32 | return GetMaterialApp(
33 | home: HomeScreen(),
34 | getPages: [
35 | GetPage(
36 | name: '/',
37 | page: () => GetxNavigationScreen(),
38 | ),
39 | GetPage(
40 | name: '/two',
41 | page: () => ScreenTwo(),
42 | ),
43 | GetPage(
44 | name: '/three',
45 | page: () => ScreenThree(),
46 | ),
47 | GetPage(
48 | name: '/four',
49 | page: () => ScreenFour(),
50 | ),
51 | GetPage(
52 | name: '/five/:param',
53 | page: () => ScreenFive(),
54 | ),
55 | ],
56 | );
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/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 29
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.example.codefactory_youtube_flutter_tutorial"
42 | minSdkVersion 16
43 | targetSdkVersion 29
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 |
--------------------------------------------------------------------------------
/lib/Screens/GetxNavigation/ScreenThree.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:get/get.dart';
4 |
5 | class ScreenThree extends StatefulWidget {
6 | @override
7 | _ScreenThreeState createState() => _ScreenThreeState();
8 | }
9 |
10 | class _ScreenThreeState extends State {
11 | int radioVal = 0;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return DefaultAppbarLayout(
16 | child: Center(
17 | child: Column(
18 | mainAxisAlignment: MainAxisAlignment.center,
19 | children: [
20 | Row(
21 | children: [
22 | Radio(
23 | groupValue: radioVal,
24 | value: 0,
25 | onChanged: (value) {
26 | setState(() {
27 | radioVal = value;
28 | });
29 | },
30 | ),
31 | Text('0'),
32 | ],
33 | ),
34 | Row(
35 | children: [
36 | Radio(
37 | groupValue: radioVal,
38 | value: 1,
39 | onChanged: (value) {
40 | setState(() {
41 | radioVal = value;
42 | });
43 | },
44 | ),
45 | Text('1'),
46 | ],
47 | ),
48 | Row(
49 | children: [
50 | Radio(
51 | groupValue: radioVal,
52 | value: 2,
53 | onChanged: (value) {
54 | setState(() {
55 | radioVal = value;
56 | });
57 | },
58 | ),
59 | Text('2'),
60 | ],
61 | ),
62 | RaisedButton(
63 | onPressed: () {
64 | Get.back(result: radioVal);
65 | },
66 | child: Text(
67 | '뒤로가기',
68 | ),
69 | ),
70 | ],
71 | ),
72 | ),
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/Screens/Retrofit/Screens/RetrofitScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/Retrofit/Retrofit/RestClient.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:retrofit/retrofit.dart';
5 | import 'package:dio/dio.dart';
6 |
7 | class RetrofitScreen extends StatefulWidget {
8 | @override
9 | _RetrofitScreenState createState() => _RetrofitScreenState();
10 | }
11 |
12 | class _RetrofitScreenState extends State {
13 | RestClient client;
14 |
15 | @override
16 | void initState() {
17 | super.initState();
18 |
19 | Dio dio = Dio();
20 |
21 | client = RestClient(dio);
22 | }
23 |
24 | renderNewsCard({
25 | @required News news,
26 | }) {
27 | return Card(
28 | child: Column(
29 | children: [
30 | Text(news.id.toString()),
31 | Text(news.title),
32 | Text(news.url),
33 | ],
34 | ),
35 | );
36 | }
37 |
38 | @override
39 | Widget build(BuildContext context) {
40 | return DefaultAppbarLayout(
41 | title: 'Retrofit Intro',
42 | child: FutureBuilder(
43 | future: client.getTopNews(),
44 | initialData: [],
45 | builder: (_, AsyncSnapshot snapshot) {
46 | if (snapshot.connectionState == ConnectionState.waiting) {
47 | return Center(
48 | child: CircularProgressIndicator(),
49 | );
50 | }
51 |
52 | final ids = snapshot.data;
53 |
54 | return ListView.builder(
55 | itemCount: ids.length,
56 | itemBuilder: (_, index){
57 | return FutureBuilder(
58 | future: client.getNewsDetail(id: ids[index]),
59 | builder: (_, AsyncSnapshot snapshot){
60 | if (snapshot.connectionState == ConnectionState.waiting) {
61 | return Center(
62 | child: CircularProgressIndicator(),
63 | );
64 | }
65 |
66 | return renderNewsCard(news: snapshot.data);
67 | },
68 | );
69 | },
70 | );
71 | },
72 | ),
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderInfiniteScroll/ProviderInfiniteScrollScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:provider/provider.dart';
4 | import 'AjaxProvider.dart';
5 |
6 | class ProviderInfiniteScrollScreen extends StatefulWidget {
7 | @override
8 | _ProviderInfiniteScrollScreenState createState() =>
9 | _ProviderInfiniteScrollScreenState();
10 | }
11 |
12 | class _ProviderInfiniteScrollScreenState
13 | extends State {
14 | @override
15 | void initState() {
16 | // TODO: implement initState
17 | super.initState();
18 |
19 | Future.microtask(() {
20 | Provider.of(context, listen: false).fetchItems();
21 | });
22 | }
23 |
24 | _renderListView() {
25 | final provider = Provider.of(context);
26 |
27 | final cache = provider.cache;
28 |
29 | final loading = provider.loading;
30 |
31 | //로딩중이면서 캐시에 아무것도 없음
32 | if(loading && cache.length == 0) {
33 | return Center(
34 | child: CircularProgressIndicator(),
35 | );
36 | }
37 |
38 | //로딩중이 아닌데 캐시에 아무것도 없음
39 | //아무것도 가져올 아이템이 없을때
40 | if(!loading && cache.length == 0) {
41 | return Center(
42 | child: Text('아이템이 없습니다.'),
43 | );
44 | }
45 |
46 | return ListView.builder(
47 | itemCount: cache.length + 1,
48 | itemBuilder: (context, index) {
49 | if (index < cache.length) {
50 | return ListTile(
51 | title: Text(
52 | cache[index].toString(),
53 | ),
54 | );
55 | }
56 |
57 | if(!provider.loading && provider.hasMore){
58 | Future.microtask(() {
59 | provider.fetchItems(nextId: index);
60 | });
61 | }
62 |
63 | if(provider.hasMore) {
64 | return Center(
65 | child: CircularProgressIndicator(),
66 | );
67 | }else{
68 | return Center(
69 | child: Text('더이상 아이템이 없습니다.'),
70 | );
71 | }
72 | },
73 | );
74 | }
75 |
76 | @override
77 | Widget build(BuildContext context) {
78 | return DefaultAppbarLayout(
79 | title: 'Provider Infinite Scroll',
80 | child: _renderListView(),
81 | );
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/lib/Layouts/ListViewLayout.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Configs/Theme.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:codefactory_youtube_flutter_tutorial/Models/index.dart';
4 |
5 | class ListViewLayout extends StatefulWidget {
6 | final List items;
7 |
8 | ListViewLayout({
9 | @required List items,
10 | }) : this.items = items;
11 |
12 | @override
13 | _ListViewLayoutState createState() => _ListViewLayoutState();
14 | }
15 |
16 | class _ListViewLayoutState extends State {
17 | _renderButton({
18 | @required ListViewItem item,
19 | }) {
20 | assert(item != null);
21 |
22 | return GestureDetector(
23 | onTap: () {
24 | Navigator.of(context).push(
25 | MaterialPageRoute(
26 | builder: (_) => item.page,
27 | ),
28 | );
29 | },
30 | child: Container(
31 | decoration: BoxDecoration(
32 | color: Colors.white,
33 | border: Border(
34 | top: BorderSide(
35 | color: THEME.greyBorderColor,
36 | ),
37 | bottom: BorderSide(
38 | color: THEME.greyBorderColor,
39 | ),
40 | ),
41 | ),
42 | child: Padding(
43 | padding: EdgeInsets.symmetric(
44 | vertical: 8.0,
45 | horizontal: 16.0,
46 | ),
47 | child: Row(
48 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
49 | children: [
50 | Text(
51 | item.name,
52 | ),
53 | Icon(
54 | Icons.chevron_right,
55 | ),
56 | ],
57 | ),
58 | ),
59 | ),
60 | );
61 | }
62 |
63 | @override
64 | Widget build(BuildContext context) {
65 | return Scaffold(
66 | appBar: AppBar(
67 | title: Text(
68 | '코드팩토리',
69 | ),
70 | ),
71 | body: ListView.separated(
72 | itemCount: widget.items.length,
73 | separatorBuilder: (context, index) {
74 | return Container(
75 | height: 8.0,
76 | );
77 | },
78 | itemBuilder: (context, index) {
79 | return _renderButton(
80 | item: widget.items[index],
81 | );
82 | },
83 | ),
84 | );
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderOptimisticResponse/PostCard.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Screens/ProviderOptimisticResponse/PostModel.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/ProviderOptimisticResponse/PostProvider.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 |
6 | class PostCard extends StatefulWidget {
7 | final int postId;
8 |
9 | PostCard({
10 | @required int postId,
11 | }) : this.postId = postId;
12 |
13 | @override
14 | _PostCardState createState() => _PostCardState();
15 | }
16 |
17 | class _PostCardState extends State {
18 | @override
19 | Widget build(BuildContext context) {
20 | final post = Provider.of(context).posts[widget.postId];
21 |
22 | return Container(
23 | child: Padding(
24 | padding: EdgeInsets.symmetric(
25 | horizontal: 16.0,
26 | vertical: 8.0,
27 | ),
28 | child: Column(
29 | children: [
30 | Padding(
31 | padding: EdgeInsets.only(
32 | bottom: 8.0,
33 | ),
34 | child: Row(
35 | children: [
36 | Text(
37 | post.title,
38 | style: TextStyle(
39 | fontSize: 16.0,
40 | fontWeight: FontWeight.w700,
41 | ),
42 | ),
43 | ],
44 | ),
45 | ),
46 | Row(
47 | children: [
48 | Text(
49 | post.content,
50 | style: TextStyle(
51 | fontSize: 14.0,
52 | color: Colors.grey,
53 | ),
54 | ),
55 | ],
56 | ),
57 | Row(
58 | children: [
59 | OutlinedButton(
60 | onPressed: () {
61 | Provider.of(
62 | context,
63 | listen: false,
64 | ).incrementLike(
65 | id: post.id,
66 | );
67 | },
68 | child: Text('좋아요 ${post.likes}'),
69 | ),
70 | ],
71 | ),
72 | ],
73 | ),
74 | ),
75 | );
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/Screens/GetxStateManagement/ReactiveScreen.dart:
--------------------------------------------------------------------------------
1 | import 'package:codefactory_youtube_flutter_tutorial/Layouts/DefaultAppbarLayout.dart';
2 | import 'package:codefactory_youtube_flutter_tutorial/Screens/GetxStateManagement/GetxController.dart';
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:get/get.dart';
6 |
7 | class ReactiveScreen extends StatefulWidget {
8 | @override
9 | _ReactiveScreenState createState() => _ReactiveScreenState();
10 | }
11 |
12 | class _ReactiveScreenState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | final controller = Get.put(ReactiveController());
16 |
17 | return DefaultAppbarLayout(
18 | title: 'Reactive',
19 | child: Center(
20 | child: Column(
21 | mainAxisAlignment: MainAxisAlignment.center,
22 | children: [
23 | Text('Reactive'),
24 | GetX(
25 | builder: (_) {
26 | return Text('Count 1 : ${_.count1.value}');
27 | },
28 | ),
29 | Obx(() {
30 | return Text('Count 2 : ${controller.count2.value}');
31 | }),
32 | Obx(() {
33 | return Text('SUM : ${controller.sum}');
34 | }),
35 | Obx(() {
36 | return Text(
37 | 'USER : ${controller.user.value.id}'
38 | '/${controller.user.value.name}',
39 | );
40 | }),
41 | Obx(() {
42 | return Text('LIST : ${controller.testList}');
43 | }),
44 | RaisedButton(
45 | onPressed: () {
46 | controller.count1++;
47 | },
48 | child: Text(
49 | 'COUNT 1 UP!',
50 | ),
51 | ),
52 | RaisedButton(
53 | onPressed: () {
54 | controller.count2++;
55 | },
56 | child: Text(
57 | 'COUNT 2 UP!',
58 | ),
59 | ),
60 | RaisedButton(
61 | onPressed: () {
62 | controller.change(id: 2, name: '레드벨벳');
63 | },
64 | child: Text(
65 | 'Change User',
66 | ),
67 | ),
68 | ],
69 | ),
70 | ),
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lib/Screens/ProviderOptimisticResponse/PostProvider.dart:
--------------------------------------------------------------------------------
1 | import 'dart:collection';
2 |
3 | import 'package:flutter/material.dart';
4 | import 'package:provider/provider.dart';
5 | import 'PostModel.dart';
6 |
7 | class PostProvider extends ChangeNotifier {
8 | LinkedHashMap posts = new LinkedHashMap();
9 |
10 | Future _fetchList() async {
11 | await Future.delayed(Duration(seconds: 1));
12 |
13 | return List.generate(
14 | 20,
15 | (index) => {
16 | 'id': index,
17 | 'title': 'title $index',
18 | 'content': 'content $index',
19 | 'likes': 0,
20 | 'dislikes': 0,
21 | },
22 | );
23 | }
24 |
25 | Future