1. #3.0 Header (16:47)
이번 강의의 목적은 flutter의 Widgets 사용에 익숙해지는 것
헤더? 위젯? 옵션?
css와 비슷하게 생각하면 됨.
flutter로 복잡한 layout 만드는데 적응 목표
rows, columns, margins, paddings, spaces에 대해서 배울것.
+decorations(배경색, 폰트, 둥근 모서리, 오버플로우 등...)
appbar : 안드로이드 스튜디오 배울때 봤던 툴바같은것인듯.
shade?
Scaffold의 body의 Column의 children은 하나의 자식만 갖지 않고, children이라는 리스트가 있다.
Row는 수평, Column은 수직 배열을 위한 것이다.
색상은 Colors.white 로도 쓸 수 있지만, Color(0xFF181818)처럼 커스텀 색상을 직접 지정할 수도 있다.
Color을 ARGB를 활용해 지정할 수도 있다. RGBO : red green blue opacity
all 말고, EdgeInsets.only(b10) t b l r 을 앞에 붙여의 방식으로 상 하 좌 우 중에 하나만 지정할 수 있다.
: 수직(v), 수평(h)을 지정할 수 있다.
2. #3.1 Developer Tools (08:06)
Developer Tools?
안드로이드 스튜디오의 컨스트레인트 레이아웃이 압도적으로 좋았던건가...?
결국은 플러터도 텍스트로 ui를 만드는건가
Column과 Row는 Alignment(정렬)가 있다.
Row의 MainAxis는 수평방향이다.
Column의 MainAxis는 수직방향이다.
Row의 CrossAxis는 세로방향이다.
Column의 CrossAxis는 가로방향이다.
Row는 가로가 메인, Column은 세로가 메인.
서로 반대 관계.
SizedBox는 그냥 size가 있는 box를 만들어준다.
fromARGB : Color.fromARGB(255, 24, 24, 24)(255가 불투명)
fromRGBO : Color.fromRGBO(24, 24, 24, 1)(1이 불투명)
Widget Inspector?
토글?가이드라인? 보여주는 기능
3. #3.2 Buttons Section (10:42)
버튼 선택?
재사용 가능한 위젯?
키보드 단축키(다음영상)
공간을 주는 SizedBox
근데 보면 볼수록 리니어 레이아웃에 가까워보이긴 한다.
Container이란것을 써볼 것
Container은 div와 같음. child를 가진 단순한 박스
<java />
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xFF181818),
body: Padding(
padding: EdgeInsets.symmetric(
horizontal: 40,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 80,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'Hey, Selena',
style: TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.w800,
),
),
Text(
'Welcome back',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 18,
),
),
],
)
],
),
SizedBox(
height: 120,
),
Text(
'Total Balance',
style: TextStyle(
fontSize: 22,
color: Colors.white.withOpacity(0.8),
),
),
SizedBox(
height: 10,
),
Text(
'\$ 5 194 482',
style: TextStyle(
fontSize: 44,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
SizedBox(
height: 30,
),
Row(children: [
Container(
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(45)),
child: Padding(
padding: EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Text(
'Transfer',
style: TextStyle(
fontSize: 20,
),
),
)),
])
],
),
)),
);
}
}
4. #3.3 VSCode Settings (06:18)
개발자경험 세팅
파란 줄 뜨는 이유? : source.fixAll
const를 쓰는것을 권장한다.
const는 컴파일 하기 전에 값을 알고있는 변수
설정->명령팔레트->open user settings(json) 파일에 작성
위와 같이 작성하면 저장할때 자동으로 const 붙여줌
위와 같이 작성하고 vs코드 재시작하면 코드로 부모자식관계를 쉽게 볼 수 있음.
설정 파일(복붙은 안됨. 어디다 넣었는지만 대충 볼 것)
{
"editor.suggestSelection": "first",
"vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
"workbench.editorAssociations": {
"*.ipynb": "jupyter-notebook"
},
"notebook.cellToolbarLocation": {
"default": "right",
"jupyter-notebook": "left"
},
"explorer.confirmDragAndDrop": false,
"workbench.colorTheme": "Material Theme Darker High Contrast",
"liveServer.settings.donotShowInfoMsg": true,
"git.autofetch": true,
"[dart]": {
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.rulers": [
80
],
"editor.selectionHighlight": false,
"editor.suggest.snippetsPreventQuickSuggestions": false,
"editor.suggestSelection": "first",
"editor.tabCompletion": "onlySnippets",
"editor.wordBasedSuggestions": false
},
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"dart.previewFlutterUiGuides": true,
"cmake.configureOnOpen": true,
"dart.openDevTools": "flutter"
}
|
다음 영상은 전구에 대해서.
5. #3.4 Code Actions (04:27)
코드 액션?
위젯을 잘라내기해서 집어넣어야 하는 것 번거로움...
전구 클릭하면 일종의 리펙토링 actions인 Code Actions
ex) Wrap with Container
Wrap with widget 하면 place holder가 잡힘.
remove도 가능함
전구 클릭 대신 단축키 사용하면 더 좋음.(내 경우는 ctrl + .)
---2023.02.03...
6. #3.5 Reusable Widgets (14:07)
이전강에서 빠진 것.
"[dart]": { 에서 "editor.formatOnSave": true, 도 설정되어있어야 함.
Error Lens라는 확장 프로그램? 미리보기?
에러 만들었을때 코드상 에러?
재사용 가능한 위젯?
위젯 통으로 선택 -> 전구 -> Extract Widget
일단 수동으로 해보면
st -> flutter StatelessWidget 생성 -> 이름 설정
클래스에 적응하기 위해 더 수동으로 하면...
작성하고 build 만들어줌. (모든 위젯은 나름의 build 메소드 필요?)
그리고 build 리턴에 위젯 적어줌.
근데 이 컴포넌트를 재사용 가능하게 하고 싶다면?
컴포넌트가 더이상 상수가 아닐때는 const를 지워야 한다.
<java />
import 'package:flutter/material.dart';
import 'package:toonflix/widgets/Button.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: const Color(0xFF181818),
body: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 80,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Text(
'Hey, Selena',
style: TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.w800,
),
),
Text(
'Welcome back',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 18,
),
),
],
)
],
),
const SizedBox(
height: 120,
),
Text(
'Total Balance',
style: TextStyle(
fontSize: 22,
color: Colors.white.withOpacity(0.8),
),
),
const SizedBox(
height: 10,
),
const Text(
'\$ 5 194 482',
style: TextStyle(
fontSize: 44,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
const SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Button(
text: 'Transfer',
bgColor: Color(0xFFF1b33b),
textColor: Colors.black,
),
Button(
text: 'Request',
bgColor: Color(0xFF1F2123),
textColor: Colors.white,
),
],
)
],
),
)),
);
}
}
<java />
import 'package:flutter/cupertino.dart';
class Button extends StatelessWidget {
final String text;
final Color bgColor;
final Color textColor;
const Button({
required this.text,
required this.bgColor,
required this.textColor,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: bgColor,
borderRadius: BorderRadius.circular(45),
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Text(
text,
style: TextStyle(
color: textColor,
fontSize: 20,
),
),
),
);
}
}
7. #3.6 Cards (13:34)
Cards?
border 만드는건 조금 시간 걸림
컨테이너 안에 위젯 넣어서 배치
https://github.com/NewChoBo/toonflix/commit/c2801df05f6db9305dc8b2466ef2fae0fbf283b8
8. #3.7 Icons and Transforms (10:01)
Row는 좌우로
Column은 상하로 나열
아이콘은 Icon(Icons.euro) 처럼 사용 가능
transform?
offset?
clipBehavior : 어떤 아이템이 오버플로우 되었을때 카드같은 컨테이너가 어떻게 동작할지 알려줌
https://github.com/NewChoBo/toonflix/commit/372efc97819b9cd3ec8bcf0d3f8bc29f573de2ca
9. #3.8 Reusable Cards (14:44)
아이콘 미리 볼 수 있다.
복습)
아이콘 만들어봄. 아이콘 크기조절, 위치 조정, 오버플로우.
margin, padding, SizedBox를 사용하면 안되었음. 카드 크기도 변했기 때문에 사용하면 안되었다.
Transform.scale? : transform 시킬 child를 받는다.
scale? : 크기 비율
offset? : 아이콘 위치(x축, y축 이동량 지정)
clipBehavior? : 디폴트는 Clip.none. 오버플로우된거 설정
Reusable Cards?
버튼 재사용한 것처럼 카드도 재사용 가능하게.
위처럼 변수를 선언하는것(앞에 언더바)는 private하게 만들것임을 의미
inverted까지 만들어주었지만, 공간을 벗어남.
scroll 가능하게 해주려면
padding 사용 전 위젯 사용해볼 것
15번째줄을 Padding 대신 SingleChildScrollView라는 위젯으로 감싸줄 것
https://github.com/NewChoBo/toonflix/commit/c59e7a6093a934846e9d473119915f3c818e7432
10. #3.9 Code Challenge (04:05)
코드 챌린지?
Transform.translate, Offset을 일일히 올리는게 맘에 들지 않으니...
currency_card.dart안에 넣어버리자 라는 목표인듯 하다.
인수로 offset 값도 보내주고.
또는 order(순서)를 정해주고 순서에 따라 오프셋값이 나오도록...
위젯이 바깥쪽에서 프로퍼티를 받는다?
이 다음 섹션에서는 interactive application을 만들 것.
유저의 입력값에 반응하는 법 배워야 함.
https://github.com/NewChoBo/toonflix/commit/0be23c0c36073823a482e3a39a74c0a05d44f09d
main.dart
<java />
import 'package:flutter/material.dart';
import 'package:toonflix/widgets/Button.dart';
import 'package:toonflix/widgets/currency_card.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
var cardOrder = 1;
return MaterialApp(
home: Scaffold(
backgroundColor: const Color(0xFF181818),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 70,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Text(
'Hey, Selena',
style: TextStyle(
color: Colors.white,
fontSize: 28,
fontWeight: FontWeight.w800,
),
),
Text(
'Welcome back',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 18,
),
),
],
)
],
),
const SizedBox(
height: 30,
),
Text(
'Total Balance',
style: TextStyle(
fontSize: 22,
color: Colors.white.withOpacity(0.8),
),
),
const SizedBox(
height: 10,
),
const Text(
'\$ 5 194 482',
style: TextStyle(
fontSize: 44,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
const SizedBox(
height: 30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Button(
text: 'Transfer',
bgColor: Color(0xFFF1b33b),
textColor: Colors.black,
),
Button(
text: 'Request',
bgColor: Color(0xFF1F2123),
textColor: Colors.white,
),
],
),
const SizedBox(
height: 100,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
const Text('Wallets',
style: TextStyle(
color: Colors.white,
fontSize: 36,
fontWeight: FontWeight.w600)),
Text(
'View All',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 18,
),
),
],
),
const SizedBox(
height: 20,
),
CurrencyCard(
name: 'Euro',
code: 'EUR',
amount: '6 428',
icon: Icons.euro_rounded,
isInverted: false,
order: cardOrder++,
),
CurrencyCard(
name: 'Bitcoin',
code: 'BTC',
amount: '9 222',
icon: Icons.currency_bitcoin,
isInverted: true,
order: cardOrder++,
),
CurrencyCard(
name: 'Dollor',
code: 'USD',
amount: '6 428',
icon: Icons.attach_money_outlined,
isInverted: false,
order: cardOrder++,
),
],
),
),
),
),
);
}
}
currency_card.dart
<java />
import 'package:flutter/material.dart';
class CurrencyCard extends StatelessWidget {
final String name, code, amount;
final IconData icon;
final bool isInverted;
final int order;
final _blackColor = const Color(0xFF1F2123);
const CurrencyCard({
super.key,
required this.name,
required this.code,
required this.amount,
required this.icon,
required this.isInverted,
required this.order,
});
@override
Widget build(BuildContext context) {
double offsetAmount = (order - 1) * -20;
return Transform.translate(
offset: Offset(0, offsetAmount),
child: Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: isInverted ? Colors.white : _blackColor,
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'no$order. $name',
style: TextStyle(
color: isInverted ? _blackColor : Colors.white,
fontSize: 32,
fontWeight: FontWeight.w600,
),
),
const SizedBox(
height: 10,
),
Row(
children: [
Text(
amount,
style: TextStyle(
color: isInverted ? _blackColor : Colors.white,
fontSize: 20,
),
),
const SizedBox(
width: 5,
),
Text(
code,
style: TextStyle(
color: isInverted
? _blackColor.withOpacity(0.8)
: Colors.white.withOpacity(0.8),
),
),
],
)
],
),
Transform.scale(
scale: 2.2,
child: Transform.translate(
offset: const Offset(-5, 12),
child: Icon(
icon,
color: isInverted ? _blackColor : Colors.white,
size: 88,
),
),
)
],
),
),
),
);
}
}
Button.dart
<java />
import 'package:flutter/cupertino.dart';
class Button extends StatelessWidget {
final String text;
final Color bgColor;
final Color textColor;
const Button({
required this.text,
required this.bgColor,
required this.textColor,
});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: bgColor,
borderRadius: BorderRadius.circular(45),
),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 50,
),
child: Text(
text,
style: TextStyle(
color: textColor,
fontSize: 20,
),
),
),
);
}
}
'공부 > Flutter' 카테고리의 다른 글
Flutter 로 웹툰 앱 만들기 #6 WEBTOON APP (0) | 2023.02.11 |
---|---|
Flutter 로 웹툰 앱 만들기 #5 POMODORO APP (0) | 2023.02.05 |
Flutter 로 웹툰 앱 만들기 #4 STATEFUL WIDGETS (0) | 2023.02.04 |
Flutter 로 웹툰 앱 만들기 #2 HELLO FLUTTER (0) | 2023.02.02 |
Flutter 로 웹툰 앱 만들기 #1 INTRODUCTION (0) | 2023.02.02 |