[flutter] flutter ์์ ์ฝ๋ ๋ถ์ - 1
android studio์์ flutter project๋ฅผ ์ฒ์ ๋ง๋ค์์ ๋ ๋ณด์ด๋ ๊ธฐ๋ณธ ์ฑ์ ์ฝ๋ ๋ถ์.
์ ์ฒด ์ฝ๋
//main.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(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
// This makes the visual density adapt to the platform that you run
// the app on. For desktop platforms, the controls will be smaller and
// closer together (more dense) than on mobile platforms.
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'), //ํ์ํ ํ๋ฉด์ ์ธ์คํด์ค
);
}
}
//์์ ํด๋์ค๊ฐ ์ค์ ๋ก ํ์ํ๋ ํด๋์ค. ์นด์ดํฐ ์ฑ ํ๋ฉด
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
//์ ํด๋์ค์ ์ํ๋ฅผ ๋ํ๋ด๋ state ํด๋์ค
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0; //ํ๋ฉด์ ํ์ํ ์ํ๊ฐ. ์นด์ดํฐ ์ซ์
//์นด์ดํฐ ๋ณ์๋ฅผ 1 ์ฆ๊ฐ์ํค๊ณ ํ๋ฉด์ ๋ค์ ๊ทธ๋ฆฌ๋ ๋ฉ์๋
void _incrementCounter() {
setState(() { //ํ๋ฉด์ ๋ค์ ๊ทธ๋ฆฌ๋๋ก ํ๋ ํจ์. statefulWidget๋ง ๊ฐ๋ฅ?
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
//ํ๋ฉด์ UI๋ฅผ ๊ทธ๋ฆฌ๋ ๋ฉ์๋. ๊ทธ๋ ค์ง ์์ ฏ์ ๋ฐํ
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold( //๋จธํฐ๋ฆฌ์ผ ๋์์ธ ๊ธฐ๋ณธ ๋ผ๋ ์์ ฏ
appBar: AppBar( //์๋จ ์ฑ๋ฐ
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center( //ํ์ํ ๋ด์ฉ
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter', //๋ณ์๋ฅผ ํ์
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter, //ํด๋ฆญ์ ์ ๋ฉ์๋ ์คํ
tooltip: 'Increment',
child: Icon(Icons.add), //์๋จ ์ฑ๋ฐ
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
์ ์ฒด ์ฝ๋๋ฅผ ๋ฉ์ด๋ฆฌ๋ก ํ์ ํด๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
import 'package:flutter/material.dart';
void main() {}
class MyApp extends StatelessWidget {}
class MyHomePage extends StatefulWidget {}
class _MyHomePageState extends State<MyHomePage> {}
์์ ์ธ ๋ฉ์ด๋ฆฌ๋ ์ฌ์ค์ ์์ ํ์ง ์๋ ๋ถ๋ถ. ์ฃผ์ ์ฝ๋๋ ์๋ ๋ ๋ฉ์ด๋ฆฌ์ ์๊ณ , ์ํ ์ฑ์ ํ๋ฉด์ ๋ํ๋ด๋ ์ฝ๋๋ค์. ์ฌ์ค์ ๋ง์ง๋ง ๋ฉ์ด๋ฆฌ์ ๋ชจ๋ ์ฝ๋๋ฅผ ์์ฑ.
์ด์ ๋ถํฐ ํ ์ค์ฉ ์ดํด๋ณด๊ฒ ์.
import 'package:flutter/material.dart';
flutter์์๋ ํ๋ฉด์ ๊ทธ๋ฆฌ๋ ๋ชจ๋ ๋์์ธ ์์๋ฅผ widget์ด๋ผ๊ณ ํจ.
importํ๋ 'package:flutter/material.dart' ํจํค์ง์๋ ๋จธํฐ๋ฆฌ์ผ ๋์์ธ ์์ ๋ค์ด ํฌํจ๋์ด ์์.
๋จธํฐ๋ฆฌ์ผ ๋์์ธ : ํ๋ซ ๋์์ธ์ ์ฅ์ ์ ์ด๋ฆฌ๋ฉด์๋ ๋น์ ๋ฐ๋ฅธ ์ข ์ด์ ๊ทธ๋ฆผ์ ํจ๊ณผ๋ฅผ ์ด์ฉํ์ฌ ์ ์ฒด๊ฐ์ ์ด๋ฆฌ๋ ๋์์ธ ๋ฐฉ์์ ๋งํ๋ค. 2014๋ ๊ตฌ๊ธ์ด ์๋๋ก์ด๋ ์ค๋งํธํฐ์ ์ ์ฉํ๋ฉด์ ๋๋ฆฌ ํผ์ง๊ธฐ ์์ํ๋ค
void main() => runApp(MyApp());
main() ์ ์ฑ์ ์์์ . runApp()์ ์ธ์๋ก MyApp()์ ์ ๋ฌํ๋ค.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(...์๋ต...);
}
}
StatelessWidget ํด๋์ค. ์ํ๊ฐ ์๋ ์์ ฏ์ ์ ์ํ๋๋ฐ ์ฌ์ฉ. => ํ ๋ฒ๋ง ๊ทธ๋ ค์ง๋ค! (๋ค์ ๊ทธ๋ ค์ง์ง ์์)
์ด๋ฐ ํด๋์ค๋ property๋ก ๋ณ์๋ฅผ ๊ฐ์ง์ง ์์. (๋ค์ ๊ทธ๋ ค์ง์ง ์์ผ๋๊น)
MyApp ํด๋์ค๋ StatelessWidget ํด๋์ค์ ์๋ธํด๋์ค.
์ด MyApp()์ runApp()์ ์ ๋ฌ๋๋ค.
StatelessWidget๋ build() ๋ฉ์๋๋ฅผ ๊ฐ์ง๋๋ฐ, ์ด ๋ฉ์๋๋ ์์ ฏ์ ์์ฑํ ๋ ํธ์ถ๋์ด ์ค์ ๋ก ํ๋ฉด์ ๊ทธ๋ฆด ์์ ฏ์ ๋ฐํ.
์ฆ, MyApp์ด build๊ฐ ๋ฆฌํดํ๋ MaterialApp() ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
build๊ฐ ๋ฐํํ๋ MaterialApp class. ์ฌ๊ธฐ๊น์ง๋ ๊ฑฐ์ ๋ชจ๋ ํ๋ก์ ํธ๊ฐ ๋์ผํจ.
title, theme, home ์ธ๊ฐ์ง ์ด๋ฆ ์๋ ์ธ์๋ฅผ ์ค์ ํด ์์ ฏ์ ์์ฑ์ ํํ.
title : ์ ๋ชฉ
theme : ํ ๋ง. ์ฌ๊ธฐ์๋ blueํ ๋ง.
home : ์ฌ๊ธฐ์ ์์ฑํ๋ ์์ ฏ์ด ์ค์ ์ด ์ฑ์ด ํ์ํ๋ ์์ ฏ์ด ๋จ.
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
์์ home ์ธ์์ ๋ค์ด๊ฐ๋ MyHomePage class.
์ํ๊ฐ ์๋ ์์ ฏ์ ์ ์ํ ๋๋ StatefulWidget class๋ฅผ ์ฌ์ฉ.
MyHomePage class์ ์์ฑ์๋ key, title์ ์ต์ ์ผ๋ก ๋ฐ์์ super๋ฅผ ์ด์ฉํด ๋ถ๋ชจ ํด๋์ค์ ์์ฑ์์ key๋ฅผ ์ ๋ฌ.
MyHomePage class๋ ์์๋ฐ์ createState()๋ฅผ ์ฌ์ ์ํด์ _MyHomePageState class์ ์ธ์คํด์ค๋ฅผ ๋ฐํ. ์ด ๋ฉ์๋๋ StatefulWidget์ด ์์ฑ๋ ๋ ํ๋ฒ๋ง ์คํ๋จ.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0; //ํ๋ฉด์ ํ์ํ ์ํ๊ฐ. ์นด์ดํฐ ์ซ์
...์๋ต...
//ํ๋ฉด์ UI๋ฅผ ๊ทธ๋ฆฌ๋ ๋ฉ์๋. ๊ทธ๋ ค์ง ์์ ฏ์ ๋ฐํ
@override
Widget build(BuildContext context) {
return Scaffold(...์๋ต...);
}
}
์ํ ํด๋์ค : State class๋ฅผ ์์๋ฐ์ ํด๋์ค. ์ํ ํด๋์ค๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ์ํ๋ฅผ ํ๋กํผํฐ ๋ณ์๋ก ํํ.
Widget build๋ _MyHomePageState ํด๋์ค์ ์ํ์ ๋ฐ๋ผ ํ๋ฉด์ ๊ทธ๋ ค์ง ์ฝ๋๋ฅผ ์์ฑ. ๋ชจ์์ ์๊น build์ ๋์ผ.
์์ ฏ์์ ์์ ฏ์ผ๋ก ๊ฐ ์ ๋ฌ?
์์ฑ์๋ฅผ ์ด์ฉ. (ex/ MyHomePage({Key key, this.title}) : super(key: key)'
์ํ ํด๋์ค์์ StatefulWidget ์ ์ ๊ทผํ๋ ค๋ฉด widget property๋ฅผ ์ฌ์ฉ. (ex/ title:Text(widget.title))
state ํด๋์ค์์๋ ์ฃผ๋ก ์ํ๋ฅผ ์ ์ฅํ ๋ณ์๋ค, ๊ทธ ๋ณ์๋ฅผ ์กฐ์ํ ๋ฉ์๋๋ฅผ ์์ฑ.
์ ์์ ์ State class๋ ๋ค์๊ณผ ๊ฐ๋ค.
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0; //ํ๋ฉด์ ํ์ํ ์ํ๊ฐ. ์นด์ดํฐ ์ซ์
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(...์๋ต...);
}
}
์ ์ํ _counter๋ 0์ผ๋ก ์ด๊ธฐํ.
_incrementCounter() method๋ setState()๋ฅผ ์คํ. setState์ ์ธ์๋ _counter++์ธ ์ต๋ช ํจ์.
setState() : ํ๋ฉด์ ๋ค์ ๊ทธ๋ฆฌ๋ ์ญํ ! => build()๋ฅผ ๋ค์ ์คํ ํ๋ค. (State class๊ฐ ์ ๊ณตํ๋ ๋ฉ์๋)
์ฆ, MyHomePage๋ StatefulWidget์ ์๋ธ ํด๋์ค์ด๋ฉฐ, ์ํ๋ฅผ ๊ฐ์ง ์ ์์.
์ํ๋ State ํด๋์ค์ ์๋ธ ํด๋์ค๋ก ์ ์. (๋ณ๊ฒฝ ๊ฐ๋ฅํ ์ํ๋ _counter)
์ด์ _MyHomePage์ build๊ฐ ํธ์ถ๋ ๋ ๋ถ๋ฆฌ๋ Scaffold class๋ฅผ ์ดํด๋ณด์.
Scaffold class๋ ๋จธํฐ๋ฆฌ์ผ ๋์์ธ ์ฑ์ ๋ผ๋๊ฐ ๋๋ ์์ ฏ. MaterialApp -> Scaffold๊ฐ ๊ธฐ๋ณธ ํํ.
์ฝ๊ฒ ๋งํ๋ฉด material design์ ๋๋ต์ ์ธ ์์น? ๋ฅผ ์ง์ ํด ๋๋ Widget.
origogi.github.io/flutter/Scafold/
Scaffold(
appBar: AppBar( //์๋จ ์ฑ๋ฐ
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter', //๋ณ์๋ฅผ ํ์
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter, //ํด๋ฆญ์ ์ ๋ฉ์๋ ์คํ
tooltip: 'Increment',
child: Icon(Icons.add), //์๋จ ์ฑ๋ฐ
),
);
์ด ์์ ์์๋ ์ธ์๋ก appBar, body, floatingActionButtion์ ์ ์.
appBar
์ฌ๊ธฐ์ AppBar class์ ๊ฐ์ฒด ์ ๋ฌ. ์๋จ์ ์ ๋ชฉ, ๋ฉ๋ด๋ฅผ ํ์ํ๋ ์์ญ.
AppBar class๋ title์ Text widget์ ์ ์. Text widget์ ๊ธ์๋ฅผ ๋ํ๋ด๋ ์์ ฏ์ด๋ฉฐ ์ธ์๋ก widget.title๋ฅผ ๋ฐ์. widget์
StatefulWidget class (MyHomePage)์ ํ๋กํผํฐ๋ฅผ ์ฐธ์กฐํ ๋ ์ฌ์ฉ.
body
_counter๋ ์ ์ํ ๋ณ์๋ผ Text ์์ ฏ์ ํ์ํ๋ ค๋ฉด ๋ฌธ์์ด๋ก ๋ณ๊ฒฝํด์ผ ํจ. ๊ทธ๋์ ๋ณ์์ ๊ฐ์ ๋ฌธ์์ด ํํ๋ก ๋ณ๊ฒฝํ๊ณ ์ ํ ๋ ๋ณ์ ์์ $๋ฅผ ๋ถ์.
floatingActionButtion
์ฌ์ฉ์๊ฐ +๋ฒํผ์ ๋๋ฅด๋ฉด ๋ค์๊ณผ ๊ฐ์ _increamentCounter() ๋ฉ์๋๊ฐ ํธ์ถ๋จ.
ํธ์ถ๋๋ฉด setState()์ ์ํด _counter++๋ฅผ ํ ๋ค, build๊ฐ ๋ค์ ํธ์ถ => ํ๋ฉด์ด ๋ค์ ๊ทธ๋ ค์ง
onPressed : ๋ฒํผ์ด ๋๋ฌ์ง๋ฉด ์คํ๋๋ ๋ถ๋ถ. ์ฌ๊ธฐ์ ๋์์ํฌ ์ฝ๋๋ฅผ ํจ์ ํํ๋ก ์์ฑ. Dart์์๋ ํจ์๋ ๊ฐ์ผ๋ก ์ฌ์ฉ ๊ฐ๋ฅ!
tooltip : ์ฌ์ฉ์๊ฐ +๋ฅผ ๊ธธ๊ฒ ํฐ์งํ ๋ ํ์ํ ๊ธ์๋ฅผ ์ง์ .
child : ์์ด์ฝ instance๋ฅผ ์ ์ํด์ +๋ชจ์ ๋ฒํผ์ ํํ.