# 강의 제목 : 누적다운로드 120만+ 1인 개발자와 함께하는 앱 개발 입문 Online
# 강의 목표 : 기초부터 운영까지 앱 개발의 전체 프로세스를 이해한다.
내 이름으로 된 앱을 최대 10개까지 만들어 출시할 수 있다.
앱 개발자로 성장할 수 있는 초석을 다진다.
반응 얻는 앱의 특징과 노하우를 알아간다.
향후 강의 없이도 나만의 앱을 개발할수 있는 실력을 가진다.
# 강의 요약 : 프로그램 설치부터 기본 문법, 광고 다는 법, 클론코딩을 진행하며 필수 지식을 학습한다.
총 10개의 다른 주제로 실제 사용화 가능한 수준의 앱을 만들어본다.
나의 앱을 세상에 선보이기 위한 개발자 등록 및 배포를 진행한다.
강사님의 리뷰/클레임 대응사례 등 앱 성공 포인트를 참고해 1인 개발자로서의 입지를 다진다.
# 강의 목차 : Flutter 실전 앱 제작
- 앱 기능 및 디자인 설계 및 초기 구조 만들기 (옷추천앱)
- 날씨 데이터 모델링
- 날씨 화면 만들기 1 - 24일차
- 날씨 화면 만들기 2 - 24일차
- 날씨별 커스텀
- 나만의 옷장
# 강의 화면 :
# 강의 내용 : 날씨 화면 만들기 1, 2
1. 앱 디자인 설계
2. 이미지 assets 추가하기
경로 : assets > img
pubspec.yaml 파일 경로 반영 하기
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
assets:
- assets/img/
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
3. 화면 이미지 구현하기
# main.dart
import 'package:cloth/cloth.dart';
import 'package:cloth/data/api.dart';
import 'package:cloth/data/preference.dart';
import 'package:cloth/data/weather.dart';
import 'package:cloth/location.dart';
import 'package:cloth/utils.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<String> clothes = ["assets/img/shirt.png", "assets/img/short.png", "assets/img/pants.png"];
List<Weather> weather =[];
List<ClothTmp> tmpCloth = [];
Weather current;
LocationData location = LocationData(lat: 37.498122, lng: 127.027565, name: "강남구", x: 0, y: 0);
List<String> sky = [
"assets/img/sky1.png",
"assets/img/sky2.png",
"assets/img.sky3.png",
"assets/img/sky4.png"];
List<String> status = [
"날이 아주 좋아요!",
"산책하기 좋겠어요",
"오늘은 흐리네요",
"우산 꼭 챙겨요!!"];
List<Color> color = [
Color(0xFFf78144),
Color(0xFF1d9fea),
Color(0xFF523de4),
Color(0xFF587d9a)
];
int level = 0;
void getWeather() async {
final api = WeatherApi();
final now = DateTime.now();
Map<String, int> xy = Utils.latLngToXY(location.lat, location.lng);
final pref = Preference();
tmpCloth = await pref.getTmp();
int time2 = int.parse("${now.hour}10");
String _time = "";
if(time2 > 2300){
_time = "2300";
}else if(time2 > 2000){
_time = "2000";
}else if(time2 > 1700){
_time = "1700";
}else if(time2 > 1400){
_time = "1400";
}else if(time2 > 1100){
_time = "1100";
}else if(time2 > 800){
_time = "0800";
}else if(time2 > 500){
_time = "0500";
}else {
_time = "0200";
}
weather = await api.getWeather(xy["nx"], xy["ny"], Utils.getFormatTime(DateTime.now()), _time);
int time = int.parse("${now.hour}00");
weather.removeWhere((w) => w.time < time);
current = weather.first;
clothes = tmpCloth.firstWhere((t) => t.tmp < current.tmp).cloth;
level = getLevel(current);
setState(() {});
}
int getLevel(Weather w){
if(w.sky > 8){
return 3;
}
else if(w.sky > 5){
return 2;
}else if(w.sky > 2){
return 1;
}
return 0;
}
@override
void initState() {
super.initState();
getWeather();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(icon: Icon(Icons.category),
onPressed: () async {
await Navigator.of(context).push(
MaterialPageRoute(builder: (ctx) => ClothPage())
);
getWeather();
},)
],
),
backgroundColor: color[level],
body: weather.isEmpty ? Container(child: Text("날씨 정보를 불러오고 있어요")) :
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(height: 50,),
Text("${location.name}", textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20
),),
Container(
width: 100,
height: 100,
margin: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Image.asset(sky[level]),
alignment: Alignment.centerRight,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("${current.tmp}°C", style: TextStyle(
color: Colors.white,
fontSize: 28
)),
Column(
children: [
Text("${Utils.stringToDateTime(current.date).month}월 ${Utils.stringToDateTime(current.date).day}일", style: TextStyle(
color: Colors.white,
fontSize: 14
)),
Text(status[level], style: TextStyle(
color: Colors.white,
fontSize: 14
)),
],
)
],
),
Container(height: 30,),
Container(child: Text("오늘 어울리는 복장을 추천해드려요", style: TextStyle(
color: Colors.white,
fontSize: 18
)),
margin: EdgeInsets.symmetric(horizontal: 20),
),
Container(height: 30,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(clothes.length, (idx){
return Container(
padding: EdgeInsets.all(8),
width: 100,
height: 100,
child: Image.asset(clothes[idx], fit: BoxFit.contain,),
);
}),
),
Container(height: 30,),
Expanded(child: Container(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: List.generate(
weather.length,
(idx){
final w = weather[idx];
int _level = getLevel(w);
return Container(
margin: EdgeInsets.symmetric(horizontal: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text("${w.tmp}°C", style: TextStyle(fontSize: 10, color: Colors.white),),
Text("${w.pop}%", style: TextStyle(fontSize: 10, color: Colors.white)),
Container(
width: 50,
height: 50,
child: Image.asset(sky[_level]),
),
Text("${w.time}", style: TextStyle(fontSize: 10, color: Colors.white)),
],
),
);
}
),
))),
Container(height: 80,),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
LocationData data = await Navigator.of(context).push(
MaterialPageRoute(builder: (ctx) => LocationPage())
);
if(data != null){
location = data;
getWeather();
}
},
tooltip: 'Increment',
child: Icon(Icons.location_on),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
# util.dart
import 'dart:math' as math;
class Utils {
static String makeTwoDigit(int number){
return number.toString().padLeft(2, "0");
}
static int getFormatTime(DateTime time){
return int.parse("${time.year}${makeTwoDigit(time.month)}${makeTwoDigit(time.day)}");
}
static DateTime stringToDateTime(String date){
int year = int.parse(date.substring(0, 4));
int month = int.parse(date.substring(4, 6));
int day = int.parse(date.substring(6, 8));
return DateTime(year, month, day);
}
}
하늘 상태 레벨
int getLevel(Weather w){
if(w.sky > 8){
return 3;
}
else if(w.sky > 5){
return 2;
}else if(w.sky > 2){
return 1;
}
return 0;
}
# 교육 소감
# 본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성되었습니다.
'코딩 알로하 :: two > 하이브리드앱' 카테고리의 다른 글
패스트캠퍼스 챌린지 26일차 (0) | 2021.11.26 |
---|---|
패스트캠퍼스 챌린지 25일차 (0) | 2021.11.25 |
패스트캠퍼스 챌린지 23일차 (0) | 2021.11.23 |
패스트캠퍼스 챌린지 22일차 (0) | 2021.11.22 |
패스트캠퍼스 챌린지 21일차 (0) | 2021.11.21 |
댓글