기본적인 구성과 위젯 사용방법
Hello World
import 'package:flutter/material.dart';
void main() {
runApp(
Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
Basic Widgets
import 'package:flutter/material.dart';
Material 라이브러리 추가
항상 main 함수가 존재 해야 한다. 말 그대로 메인 함수
runApp() 함수, 앱의 시작점, 루트
내부의 위젯들로 위젯트리 구성, flutter 프레임워크는 루트 위젯으로 화면 전체를 덮는다.
Center 위젯과 자식 위젯으로 Text 위젯
직관적인 이름으로 설명 필요없음
import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
MyAppBar({this.title});
// Fields in a Widget subclass are always marked "final".
final Widget title;
@override
Widget build(BuildContext context) {
return Container(
height: 56.0, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: Row(
// <Widget> is the type of items in the list.
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child to fill the available space.
Expanded(
child: title,
),
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}
class MyScaffold extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Material is a conceptual piece of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: <Widget>[
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context).primaryTextTheme.title,
),
),
Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}
void main() {
runApp(MaterialApp(
title: 'My app', // used by the OS task switcher
home: MyScaffold(),
));
}
MaterialApp
Material 테마가 적용된 앱 생성
기본적으로 위젯을 포함하고 있다. (네비게이터(라우트))
home 속성
앱 첫 시작화면 설정 속성
StatelessWidget & StatefulWidget
StatelessWidget: 상태 저장이 필요없는 위젯
StatefulWidget: 상태 저장이 필요한 위젯
기본적으로 위젯은 위의 2가지를 상속받아 새 위젯을 생성한다. (커스텀 위젯)
StatelessWidget 또는 StatefulWidget을 상속받는 위젯은 반드시 build 함수 override 해야 한다.
@override Widget build(BuildContext context) {}
Material Class(위젯)는 Material 속성을 가진 Container? 같은 느낌?
A piece of material 이라고 문서에 되어있는데 아직 이해가 안감.
Column으로 레이아웃을 잡아준다.
Expanded 속성은 다음 위젯 전까지의 공간을 차지한다는 뜻이다.
각 위젯은 style 속성이 존재. 색상, 스타일들을 정해줄 수 있다.
Using Material Components
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Flutter Tutorial',
home: TutorialHome(),
));
}
class TutorialHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Scaffold is a layout for the major Material Components.
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: Text('Example title'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: Center(
child: Text('Hello, world!'),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
child: Icon(Icons.add),
onPressed: null,
),
);
}
}
위에서 Appbar와 Scaffold 위젯이 MaterialApp이 포함된 위젯
Scaffold는 Material Components를 위한 레이아웃 중 하나
leading 속성
Title 전에 오는 위젯
actions 속성
Title 뒤에 오는 위젯
Handling gestures
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('MyButton was tapped!');
},
child: Container(
height: 36.0,
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.lightGreen[500],
),
child: Center(
child: Text('Engage'),
),
),
);
}
}
GestureDetector
MyButton 클래스의 Container를 탭 할 시에 onTap 콜백 함수가 실행 됨
Changing widgets in response to input
class Counter extends StatefulWidget {
// This class is the configuration for the state. It holds the
// values (in this case nothing) provided by the parent and used by the build
// method of the State. Fields in a Widget subclass are always marked "final".
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
// 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++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance
// as done by the _increment 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 Row(
children: <Widget>[
RaisedButton(
onPressed: _increment,
child: Text('Increment'),
),
Text('Count: $_counter'),
],
);
}
}
StatefulWidget과 State는 독립된 객체다.
Widget 내부에 State가 없는 것은 계획된 설계.
두 객체의 차이점은 생명주기가 다르다는 것이다.
위젯은 임시 객체, State 객체는 영속적이다.
createState() 함수
StatefulWidget을 상속받는 객체는 createState() 함수를 override 해야한다.
setState() 함수는 상태 변경 시 발생하는데(위에서는 onPressed에서 콜백) 호출이 되면 build 함수를 재실행 시킨다.
Flutter 프레임워크는 build 함수를 최적화 시켜서 객체를 새로 생성시키는 것보다 build를 재실행 시키는 것이 더 효율적이다.
위에서 setState() 함수를 통하지 않고 _counter 값을 변경 시키면 아무 일도 일어나지 않는다.
좀 더 객체지향적인 코드(위의 예제에서 캡슐화 좀 더 진행)
class CounterDisplay extends StatelessWidget {
CounterDisplay({this.count});
final int count;
@override
Widget build(BuildContext context) {
return Text('Count: $count');
}
}
class CounterIncrementor extends StatelessWidget {
CounterIncrementor({this.onPressed});
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: onPressed,
child: Text('Increment'),
);
}
}
class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
++_counter;
});
}
@override
Widget build(BuildContext context) {
return Row(children: <Widget>[
CounterIncrementor(onPressed: _increment),
CounterDisplay(count: _counter),
]);
}
}
'Flutter' 카테고리의 다른 글
BLoC 개념 (0) | 2019.01.13 |
---|---|
2. 레이아웃 기초 (0) | 2019.01.03 |
댓글