4주차 플러터 스터디에서는 튜토리얼 영상 #15-17을 참고하여 공부했다.
Flutter Tutorial for Beginners #15 - Ninja ID Project
지금까지 배웠던 플러터의 위젯 특성들을 활용하여, 플러터 데모 앱을 만들어보는 실습 강의였다.
- ‘Create New Flutter Project’ 클릭 → ‘test’ 폴더 삭제하기
- main.dart 파일에서 void main()⇒runApp(MyApp()); 이하 모두 삭제하기
- MyApp() 대신 다음 코드 작성:
MaterialApp(
home: NinjaCard(),
)
*home property는 어플의 홈 스크린에 보여지는 것들을 결정하는 property이다.
*Scaffold→ 빠르게 어플의 layout을 만들어준다.
4. Stateless Widget 추가:
class NinjaCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
title: Text('Ninja ID Card'),
centerTitle: true,
backgroundColor: Colors.grey[850],
elevation: 0.0,
),
body: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 40.0, 30.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: CircleAvatar(
radius: 40.0,
backgroundImage: AssetImage('assets/thumb.jpg'),
),
),
Divider(
color: Colors.grey[800],
height: 60.0,
),
Text(
'NAME',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'Chun-Li',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'HOMETOWN',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'Beijing, China',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'CURRENT NINJA LEVEL',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'8',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Icon(
Icons.email,
color: Colors.grey[400],
),
SizedBox(width: 10.0),
Text(
'chun.li@thenetninja.co.uk',
style: TextStyle(
color: Colors.grey[400],
fontSize: 18.0,
letterSpacing: 1.0,
),
)
],
),
],
),
),
);
}
}
5. 새로운 directory 생성 → ‘assets’ 폴더 생성 → 이미지 추가 → pubspec.yaml 파일 선언 후 새로고침
이미지를 사용하기 전, 반드시 pubspec.yaml 파일에 다음과 같이 선언해야한다:
assets:
- assets/파일명.파일확장자
→ ‘Get dependencies’ 클릭 (pubspec.yaml 파일에 변화를 주었기 때문에 클릭해야한다.)
Flutter Tutorial for Beginners #16 - Stateful Widgets
지난 강의에서는 동적 데이터 또는 동적 상태를(dynamic data or dynamic states) 사용하지 않았기 때문에 StatelessWidget을 사용해도 무방했다.
* Statelesswidget은 생성되고나서 거의 바뀌지 않으며, 시간에 따라 변화하는 states나 data를 포함하지 않는 Widget이다. (예: 버튼을 클릭하는 것)
만약 어플에 시간에 따라 변화하는 동적 데이터를 표현하고자 한다면, 우리는 StatefulWidget을 사용해야한다.
* Statefulwidget은 시간에 따라 state가 변화할 수 있으며, 시간에 따라 바뀌는 동적 데이터를 포함할 수 있는 Widget이다. (예: 버튼 클릭에 따라서 숫자가 증가하는 것)
Widget build(BuildContext context){
return
}
class Test extends StatefulWidget {
@override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
int counter = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
title: Text('Ninja ID Card'),
centerTitle: true,
backgroundColor: Colors.grey[850],
elevation: 0.0,
),
body: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 40.0, 30.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: CircleAvatar(
radius: 40.0,
backgroundImage: AssetImage('assets/thumb.jpg'),
),
),
Divider(
color: Colors.grey[800],
height: 60.0,
),
Text(
'NAME',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'Chun-Li',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'HOMETOWN',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'Beijing, China',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'CURRENT NINJA LEVEL',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'8',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Icon(
Icons.email,
color: Colors.grey[400],
),
SizedBox(width: 10.0),
Text(
'chun.li@thenetninja.co.uk',
style: TextStyle(
color: Colors.grey[400],
fontSize: 18.0,
letterSpacing: 1.0,
),
)
],
),
],
),
),
);
};
}
}
StatelessWidget을 StatefulWidget으로 바꾸기
* Flutter에서 변수를 출력하는 방법: ' dollar sign($) + 변수명 ' (예: $ninjaLevel)
class NinjaCard extends StatefulWidget {
@override
_NinjaCardState createState() => _NinjaCardState();
}
class _NinjaCardState extends State<NinjaCard> {
int ninjaLevel = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
appBar: AppBar(
title: Text('Ninja ID Card'),
centerTitle: true,
backgroundColor: Colors.grey[850],
elevation: 0.0,
),
body: Padding(
padding: const EdgeInsets.fromLTRB(30.0, 40.0, 30.0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(
child: CircleAvatar(
radius: 40.0,
backgroundImage: AssetImage('assets/thumb.jpg'),
),
),
Divider(
color: Colors.grey[800],
height: 60.0,
),
Text(
'NAME',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'$ninjaLevel', //Output the variable 'ninjaLevel'
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'HOMETOWN',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'Beijing, China',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Text(
'CURRENT NINJA LEVEL',
style: TextStyle(
color: Colors.grey,
letterSpacing: 2.0,
),
),
SizedBox(height: 10.0),
Text(
'8',
style: TextStyle(
color: Colors.amberAccent[200],
fontWeight: FontWeight.bold,
fontSize: 28.0,
letterSpacing: 2.0,
),
),
SizedBox(height: 30.0),
Row(
children: <Widget>[
Icon(
Icons.email,
color: Colors.grey[400],
),
SizedBox(width: 10.0),
Text(
'chun.li@thenetninja.co.uk',
style: TextStyle(
color: Colors.grey[400],
fontSize: 18.0,
letterSpacing: 1.0,
),
)
],
),
],
),
),
);
};
}
}
위의 코드를 실행할 경우, 다음과 같은 에러가 발생: ‘NinjaCard’ is not a subtype of stateless widget
→ 에러 해결 방법: Run 패널에서 'Hot refresh' 또는 'Hot restart' 클릭
데이터를 수정/재설정하는 경우, Hot restart를 눌러야 변동된 데이터가 반영이 된다.
이러한 번거로움은 setState 함수를 통해 해결할 수 있다.
우선, Scaffold 내부에, AppBar 속성 아래에 다음과 같은 코드를 삽입한다:
floatingActionButton : FloatingActionButton(
onPressed: () {
ninjaLevel += 1;
},
child: Icon(Icons.add),
backgroundColor: Colros.grey[800],
),
코드를 삽입하게 되면, NinjaLevel의 값은 변하지 않는다. 즉, 우리가 의도한 결과가 나오지 않는 것을 확인할 수 있다.
따라서, 위 코드 속 ninjaLevel += 1; 대신, 우리는 아래와 같이 setState라는 함수를 사용할 것이다:
floatingActionButton : FloatingActionButton(
onPressed: () {
setState(() {
ninjaLevel += 1;
})
},
child: Icon(Icons.add),
backgroundColor: Colros.grey[800],
),
setState는 build를 재실행(rerun)하게끔한다. 따라서, 이렇게 ‘setState’를 사용하면 원하는 결과가 나오는 것을 알 수 있다.
Flutter Tutorial for Beginners #17 - Lists of Data
위젯 내에서 동적으로 여러 데이터(lists of data)를 순환하며 이들을 출력하는 방법에 대해 알 수 있었던 영상이었다.
1. 'Create New Project' 클릭 → (불필요한) test folder 삭제
* 이때 Test 폴더 지우는 이유: 폴더 속에 있는 'widget_test.dart' 파일에서 'MyApp'을 참조하는데, 이것이 에러를 유발한다!
2. main.dart 코드 다음과 같이 작성:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: QuoteList()
));
/* We need a stateful widget because we need some changing data inside this widget
(we’re going to have a list of data we cycle through ultimately
and it’s going to output to the screen so data could be changing)*/
class QuoteList extends StatefulWidget {
@override
_QuoteListState createState() => _QuoteListState();
}
class _QuoteListState extends State<QuoteList> {
List<String> quotes = [
'Be yourself; everyone else is already taken',
'I have nothing to declare except my genius',
'The truth is rarely pure and never simple'
];
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
title: Text('Awesome Quotes'),
centerTitle: true,
backgroundColor: Colors.redAccent,
),
body: Column(
children: quotes.map((quote) => Text(quote)).toList(),
),
);
}
}
'3-2기 스터디 > 플러터' 카테고리의 다른 글
[6주차] Codelab - Basic Flutter layout concepts (0) | 2022.06.23 |
---|---|
[5주차] 튜토리얼 영상 #18-#22 (0) | 2022.05.31 |
[3주차] 튜토리얼 영상 #8-#14 (0) | 2022.05.03 |
[2주차] 튜토리얼 영상 #4-#7 (0) | 2022.04.08 |
[1주차] 튜토리얼 영상 #1-#3 (0) | 2022.04.07 |
댓글