1. 프로젝트 만들기
flutter create hello-world!
Bash
복사
2. 프로젝트 둘러보기
•
.idea : configuration for Android Stuido
•
android : 안드로이드 프로젝트 전체를 담고있음
◦
최종적으로 Flutter 가 native 코드를 만들면 여기로 들어감
◦
거의 건들일이 없음
•
build : output of Flutter application
◦
배포할때 쓰는거고
◦
플러터가 알아서 관리하니까 볼일 없음
•
IOS : IOS 프로젝트 전체를 담고있음
◦
안드로이드 폴더와 마찬가지
•
lib : Dark파일들
◦
우리가 주로 쓰는 폴더
•
test : 테스트 할떄 쓰임
•
pubspec.yaml : 프로젝트의 dependency 를 관리
◦
우리가 주로 쓰게 될 파일
◦
최종적으로 pubspec.lock 으로 자세한 내용이 적힌다.
•
기타파일 : 플러터가 알아서 씀
3. Dart 둘러보기
•
Dart 언어 정리해둔거 확인
4. main.dart 만들어보기
•
main 함수는 Flutter 에 의해 앱이 실행될때 자동으로 호출된다.
◦
따라서 파일이름도 main.dart 이어야함.
위젯 만들어보기
•
pubspec.yaml 에 dependencies 로 flutter 가 있기 때문에
•
플러터에서 구현해둔 클래스 등등을 쓸수있다.
import 'package:flutter/material.dart';
Bash
복사
•
위와 같이 dependency 를 불러올수있다.
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(home: Text('Hello!!'));
}
}
Dart
복사
•
StatelessWidget 이라는 클래스를 상속받아서 나만의 위젯을 만든다.
◦
이때 build 라는 메소드가 구현되어야한다.
◦
해당 위젯의 메타정보가 담겨있는 context 를 받아 Widget을 반환하는 함수이다.
•
MaterialApp 위젯
◦
생성자로 필요한 인자를 넘겨주면 된다.
◦
home : 어플의 바탕이 되는부분
•
@overrid 데코레이터
◦
메소드가 override 됨을 명시함
◦
안해도 되긴하는데 하면 실수를 줄일수있다.
void main() {
runApp(MyApp());
}
void main() => runApp(MyApp());
Dart
복사
•
runApp()
◦
material.dart 에 expose 되어있는 함수
◦
어플에 화면을 뿌리는 함수
◦
인자로 root 위젯을 넣어주면
◦
위젯의 build 함수를 호출한다.
•
성공!
•
근데 못생겼어
스타일링 해보기
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("My First App!"),
),
body: Text("asdf")
),
);
Dart
복사
•
Scaffold 위젯
◦
어플을 어플처럼 보이도록하는 기본 UI 가 탑재되어있다.
◦
Ctrl-Space 로 사용가능한 매개변수들 확인 가능
◦
appBar : 어플리케이션에 위에 Bar 부분
◦
body : 어플리케이션 바탕부분
•
AppBar 위젯
◦
title : AppBar의 타이틀
•
나쁘지 않네
5. 간단한 퀴즈 어플 만들기
위젯의 종류
•
Visible 위젯
◦
실제로 보이는 위젯
◦
Text, Card, RaisedButton 등
•
Invisible 위젯
◦
실제로 보이지는 않는 위젯
◦
visible 위젯이 어떻게 화면에 보여질지 컨트롤
◦
레이아웃을 정해주는 위젯
◦
Row, Column, ListView 등
•
Container 위젯
◦
실제로 보이지 않아 Invisible 위젯 같지만
◦
눈에 보이는 스타일링을 할수있다.
레이아웃 해보기
body: Column(
children: [
Text("The question!"),
RaisedButton(
child: Text('Answer 1'),
onPressed: null,
),
RaisedButton(
child: Text('Answer 3'),
onPressed: null,
),
RaisedButton(
child: Text('Answer 2'),
onPressed: null,
),
],
)),
Dart
복사
•
Column 위젯
◦
위젯들을 열(세로)로 배치한다.
◦
children : 위젯의 배열
•
RaisedButton 위젯
◦
플러터의 가장 기본적인 버튼
◦
child : 버튼에 들어갈 내용
◦
onPressed : 클릭시 행동할 함수 (함수그 자체를 넘겨줘야한다.)
함수 만들기
•
클래스 밖에 함수를 만드는것은 좋지 않다.
•
각 위젯은 standalone 하게 작동해야한다.
•
그래서 클래서 내부에 선언한다.
void answerQuestion() {
print('Answer chosen!');
}
Dart
복사
•
아래와 같이 인자로 넘겨준다.
•
이때 함수를 실행해서 넘기면 안되고
•
함수그 자체를 넘겨줘야한다.
children: [
Text("The question!"),
RaisedButton(
child: Text('Answer 1'),
onPressed: () => print("Answer 1 Chosen!"),
),
RaisedButton(
child: Text('Answer 2'),
onPressed: () {
print("Answer 2 Chosen!");
},
),
RaisedButton(
child: Text('Answer 3'),
onPressed: answerQuestion,
),
],
Dart
복사
•
익명 함수를 써도 상관 없다.
•
이렇게 함수를 써도 위젯의 글씨를 바꾼다거나 하지 못한다
•
어떻게 바꾸지?
state 이해하기
•
어플또는 위젯에서 쓰일 데이터를 의미
•
지금 까지 StatelessWidget 를 써왔기 떄문에 state가 존재하지 않았다.
•
그럼 State를 쓰기 위해서는 어떻게 해야할까
•
Stateless
◦
위젯 → UI랜더링
◦
이때 생성자로 Input Data(외부 데이터)가 넘어갈수있음
◦
만약 이 Input Data(외부 데이터)가 수정되면 rerender 된다.
•
Stateful
◦
위젯(내장 데이터) → UI 랜더링
◦
마찬가지로 생성자로 Input Data(외부 데이터)가 넘어갈수있음
◦
내장 데이터 , 외부 데이터 모두 수정되면 rerender 된다.
StatefulWidget 으로 화면 바꾸기
•
2개의 클래스로 이루어져있다.
◦
createState를 갖고있는 클래스
◦
build 함수가 구현되어있는 클래스
•
이렇게 클래스 하나를 감싸는 이유
◦
State 클래스 자체는 rerender 되지 않는다...?
class MyApp extends StatefulWidget() {
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
var index = 0;
void click() {
setState(() {
index = index + 1;
})
}
Widget build(BuildContext context) {
var texts = [
'abc',
'def',
]
return MaterialApp(home: Text(texts[index]));
}
}
Dart
복사
•
createState 메소드의 반환값으로 MyAppState를 넘겨준다.
•
setState는 UI 를 rerender 시킨다. 전체는 아니고 해당 클래스의 build 함수를 다시 부름
•
하지만 여전히 엄청 비효율적 → 그래서 자체적으로 다 그리진 않고 뭐가 바꼈는지만 찾아서 변경함
•
그래서 setState 없이는 화면이 바뀌지 않음
•
보통 클래스를 외부에 보여주지 않기 위해서 _ 를 붙여서 private화 시킨다.
public 함수에서 같은 클래스에있는 private 변수에 접근 못하나요?
생성자로 위젯 만들기
•
질문을 그리는 위젯을 따로 뽑아보자
•
일반적으로 파일 하나에 위젯하나
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
Widget build(BuildContext context) {
return Text(questionText)
}
}
Dart
복사
•
이런식으로 생성자로 Input Data(외부 데이터)를 받아올수있다.
import './question.dart'; //상대 경로
Dart
복사
•
위와같이 파일을 불러와서 위젯을 쓰면 된다.
•
이 위젯을 쓰는 위젯의 build 함수가 다시 호출되면서 rerender 된다.
•
어자피 Stateless 이라서 변수가 바뀔일이 없으니 final 키워드를 써주도록하자
텍스트 스타일링 해보기
return Text(
questionText,
style: TextStyle(fontSize: 28),
textAlign: TextAlign.center,
)
Dart
복사
•
TextAlign.center 가 enum으로 정의 되어있다.
•
Text 위젯
◦
말 그대로 텍스트 위젯
◦
style: 텍스트 스타일
◦
textAlign: 텍스트 위치
컨테이너 위젯
return Container(
width: double.infinity,
margin: EdgeInsets.all(10),
child: Text(),
)
Dart
복사
•
Container 위젯
◦
기본적으로 보이지 않음
◦
child: 자식 위젯
◦
margin: 여백 설정 (EdgeInsetsGeometry 클래스를 넘겨줘야함)
•
폭을 무한으로하면 위젯이 가질수있는 최대값이 된다 ..?
•
이런식으로 content(child)의 위치를 조정할수있음
•
EdgeInsets.all(10)은 EdgeInsetsGeometry 클래스를 상속하는 클래스의 생성자이다.
답변 체크 구현하기
•
이전에 구현해뒀던 _answerQuestion 함수로 질문의 답을 정할수있다.
•
이떄 Answer 를 위젯으로 뺐기 때문에 함수를 생성자로 넘겨준다.