Flutter 기초
Updated:
1.플로터 앱페이지 기본 코드 이해하기
main.dart
의 기본적인 이해 하기
// 필수 material ui package
import 'package:flutter/material.dart';
// futter 에서 최상위에 위치하는 widget 인 runApp() 은 항상 argument 를 widget 를 가져와야 함
void main() => runApp(MyApp());
// MyApp 은 정적인 state 임으로 statelessStatement 로 만들어야 함
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// MaterialApp 이 MyApp 밑에 위치하고 실질적으로 모든 위젯을 감싸는 위젯
return MaterialApp(
// 이 타이틀은 App 의 이름을 총칭하는 title
title: 'First app',
// ThemData는 app의 기본적인 테마를 지정하는 위젯
theme: ThemeData(
// primaryWatch 는 어떠한 특정한 색상을 primeColor 로 지정해서 사용하겠다는 의미를 말함
// material ui 에서 제공하는 색상 중에서 blue 라는것을 지정
primarySwatch: Colors.blue),
// home 은 App 이 정상적으로 실행 되었을때 보여주는 경로임
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
// scaffold 위젯은 화면에 표현할때 최상단 구조 뼈대 위젯을 말함 마치 위젯을 그리기 위한 도화지 같은것임 scaffold 가 없으면 위젯을 그리지 못함
return Scaffold(
// 화면의 최상단에 위치되는 위젯인 AppBar
appBar: AppBar(
// Text 위젯은 text 를 사용할수 있는 위젯 string 형태로 argument 를 가짐
// appBar 위에 title 은 화면에 출력되는 title 을 가리킴
title: Text('First App'),
),
// body 는 scaffold 에서 body 부분을 그릴 수 있는 위젯
// body 부분에서 중앙에 위치 시킬수 있는 위젯 Center
body: Center(
// Center 안에 child 를 가질 수 있는데 Column() 위젯을 가져 올수 있는데 그 안에 모든 요소들을 세로로 배치 할 수 있는 위젯
child: Column(
// 요소들을 세로로 배치해야되기 때문에 children 의 list 를 가져옴
children: <Widget>[
Text('Hello'),
Text('Hello'),
Text('Hello'),
],
),
),
);
}
}
2.Class 와 Widget
-
Class : 객체가 가져야하는 속성과 기능을 정의한 내용을 담고 있는 설계도 역활
-
Object (객체): class 가 정의된 후 메모리상에 할당되었을 때 이를 객체라고 함
-
Instance: class 기반으로 생성되며, 클래스의 속성과 기능을 똑같이 가지고 있고 프로그래밍 상에서 사용되는 대상임
// class, constructor, instance, widget 에 대한 개념 예시
class Person {
// class type 선언
String name;
int age;
String sex;
// Constructor with named argument
// named 로 만들게 되면 optional 한 argument 값이 되서 입력을 안받아도 됨
// 순서도 상관이 없게 됨
Person({String name, int age, String sex}) {
this.name = name;
this.age = age;
this.sex = sex;
}
}
void main() {
// instance 생성
// flutter 에서는 아래와같이 widget에서 named argument 형태로 사용함
// 예를 들어 appBar: 위젯명(), body: 위젯명(), 이런식으로 사용함
// 그래서 widget 이 class 인데 사용되는건 constutor 에 생성된 named argument 를 집에 넣어서 instance 형태로 widget 을 사용하는 것임
Person p1 = Person(age: 30);
Person p2 = Person(sex: 'male');
print(p1.age);
}
3.AppBar 메뉴 아이콘 추가하기
-
leading
: 아이콘 버튼이나 간단한 위젯을 왼쪽에 배치 할때 사용합니다 -
actions
: 복수의 아이콘 버튼 등을 오른쪽에 배치할때 사용합니다 -
onPressed
: 함수의 형태로 일반 버튼이나 아이콘 버튼을 터치했을 때 일어나는 이벤트를 정의 하는 곳입니다.
lass MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Appbar icon Menu'),
centerTitle: true,
elevation: 0.0,
// leading : 위젯이나 아이콘등을 타이틀 왼쪽에 위치 시키는것 (AppBar, ListTile 등에서 사용됨)
leading: IconButton(
icon: Icon(Icons.menu),
// IconButton 을 누르면 실행될 action 함수 설정
onPressed: () {
print('Menu button is clicked');
},
),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {
print('Shopping cart button is clicked');
},
),
IconButton(
icon: Icon(Icons.search),
onPressed: () {
print('Search button is clicked');
},
),
],
),
);
}
}
4.Drawer 메뉴 만들기
-
Drawer
는 햄버거 메뉴 버튼을 누르게 되면 옆에서 창이 나타나면서 추기적인 내용을 작성 할 수 있는 기능을 말합니다.drawer
를 만들게 되면 appBar 시작 부분에 자동으로 햄버거 메뉴가 생성이 됩니다 -
ListView
위젯은 복수의 위젯을 나열하는 위젯리스트가children
속성을 통해서 호출됩니다. 그 하나하나를ListTile
이라고 합니다.ListTile
안에는icon, title, button
등이 사용됩니다
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
UserAccountsDrawerHeader(
currentAccountPicture: CircleAvatar(
backgroundImage: AssetImage('assets/sample.png'),
backgroundColor: Colors.white,
),
// 다른 account 사진 설정
otherAccountsPictures: const <Widget>[
CircleAvatar(
backgroundImage: AssetImage('assets/sample.png'),
backgroundColor: Colors.white,
)
],
accountName: Text('Jacob'),
accountEmail: Text('jacobkosmart@gmail.com'),
// 디테일 버튼 누르면 실행될 코드
onDetailsPressed: () {
print('arrow is clicked');
},
// UserAccountDraweHeader 부분 box 크기 조정
decoration: BoxDecoration(
color: Colors.lightBlue[200],
// hearder 밑 부분 라운드 처리
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40.0),
bottomRight: Radius.circular(40.0),
),
),
),
// ListTile
ListTile(
leading: Icon(
Icons.home,
color: Colors.grey[850],
),
title: Text('Home'),
onTap: () {
print('Home is Clicked');
},
// leading 과 반대로 뒤에 붙는 trailing
trailing: Icon(Icons.add),
),
ListTile(
leading: Icon(
Icons.settings,
color: Colors.grey[850],
),
title: Text('Setting'),
onTap: () {
print('Setting is Clicked');
},
// leading 과 반대로 뒤에 붙는 trailing
trailing: Icon(Icons.add),
),
ListTile(
leading: Icon(
Icons.question_answer,
color: Colors.grey[850],
),
title: Text('Q&A'),
onTap: () {
print('Q&A is Clicked');
},
// leading 과 반대로 뒤에 붙는 trailing
trailing: Icon(Icons.add),
),
],
),
),
5. BuildContext
첫번째 정의
-
A handle to the location of a widget in the widget tree : “widget tree 에서 현재 widget 의 위치를 알 수 있는 정보 를 말합니다
-
flutter 의 widget 은 함수 method 인 build method 를 자기고 있습니다. 이것을 통해서 계층구조로 만들어 갑니다 (에, Widget 1 => widget 2 => …)
-
build method 는 scaffold widget 을 return 하는데, widget tree 상에서 어디에서 위치하고 있는지 정보를 가지고 있는 context 라는 것을 넣어서 return 해주는것이라고 보면 됩니다.
두번째 정의
-
Each widget has its own BuildContext, which becomes the parent of the widget returned by the StatelessWidget.build or State.build function : 이 BuildContext 는 stateless 위젯이나 state 빌드 메서드에 의해 리턴된 위젯의 부모가 됩니다
-
만약 Scaffold() 의 위치가 필요해서, 현재 Scaffold 위젯의 context 를 참조하면 원래 되야 되는데, 참조하게 되면 에러가 발생되는데
"Scaffold.of() called with a context that dose not contain a Scaffold"
라고 에러가 발생됩니다. 왜냐면 context 는 Scaffold 가 widget tree 상에서의 정보를 가지고 있지 않기 때문에 error 가 발생된것입니다. -
그래서 해결방법은 Scaffold widget 에 물려받은 위젯의 context 를 가지고 알 수 있게 할 수 있습니다.
6.Container Widget
-
Containers with no children try to be as big as possible : Container 위젯은 페이지 안에서 최대한의 공간을 차지 하려고 한다는 의미 입니다.
-
Containers with children size themselves to their children. : Container 는 children 을 가지게 되면 그 child 의 크기대로 줄어 든다는 의미 입니다.
-
Container
는 오직 하나만의child
만 가질 수 있습니다
class MyPage extends StatelessWidget {
const MyPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Container'),
centerTitle: true,
),
// safeArea 를 사용해서 화면 밖으로 나가지 않게 하는 widget
body: SafeArea(
child: Container(
// children 이 없을 경우에 screen 전체 화면을 차지함
color: Colors.red,
width: 100,
height: 100,
// symentric 을 사용하게 되면 상하 값, 좌우 값을 지정함
margin: const EdgeInsets.symmetric(
vertical: 50,
horizontal: 10,
),
// Continer 안에 포함되는 사이의 거리 값임
padding: const EdgeInsets.all(40.0),
// child 가 있을때 Text 의 사이즈 만큼 Container 가 작아짐
child: Text('Hello'),
),
),
);
}
}
7.Column / Row widget
Column
-
Center
widget 은 Column 에서 좌우를 조절 해서 center 위치 하지만 상하 mainAxis 방향은 따로 설정을 해줘야 합니다 -
방법은
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
2 가지 인데 두개는 통제하는 범위에 따라서 쓰임세가 약간 다름니다
mainAxisAlignment: MainAxisAlignment.center
mainAxisSize: MainAxisSize.min,
verticalDirection
- verticalDirection 은 children 에 있는 위치를 어디서 부터 하는지를 정하는 위젯입니다. (up 하게 되면 역순으로 밑에서부터 1,2,3 순으로 됨)
MainAxisAlignment.spaceEvenly
- 간격 조정에서 spaceEvenly 는 각 children 의 item 들의 간격을 일정하게 해줍니다.
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
MainAxisAlignment.spaceBetween
- spaceBetween 은 스크린에 상 중 하 에 딱 붙어서 배치하게 됨
mainAxisAlignment: MainAxisAlignment.spaceBetween,
MainAxisAlignment.spaceAround
- spaceAround 은 스크린의 끝부분과 children 사이의 간격 모두 동일하게 위치합니다
crossAxisAlignment: CrossAxisAlignment.end
container 를 cross 축으로 최대한 end point 까지 맞추는 설정값 입니다.
Container(
width: double.infinity,
)
crossAxisAlignment: CrossAxisAlignment.stretch,
- 가로방향으로 꽉 채워주기 위해선 stretch 해주면 각 container 에 상관 없이 가로 옆으로 꽉 차게 됩니다
SizedBox
- Container 사이에 투명 박스를 위치 시켜 개별적으로 container 사이의 간격을 조정할 수 있습니다.
Container(
width: 100,
height: 100,
color: Colors.red,
child: Text('Container 1'),
),
SizedBox(
height: 50.0,
),
Container(
width: 200,
height: 100,
color: Colors.yellow,
child: Text('Container 2'),
),
body: Center(
// Column 에서 center 는 좌우 center 속성만 관여하게 됨
child: Column(
// 상하 축 Center 속성을 주기 위해서는 mainAxisAlignment 에서 center 속성을 주어야 함
// mainAxisAlignment: MainAxisAlignment.center,
// 상하의 통제권을 같기 위해서는 mainAxisSize 속성을 사용함
// mainAxisSize: MainAxisSize.min,
// verticalDirection 은 children 에 있는 위치를 어디서 부터 하는지를 정하는 위젯입
// verticalDirection: VerticalDirection.up, // up 하게 되면 1이 아래서부터 나열됨
// 간격 조정에서 spaceEvenly 는 각 children 의 item 들의 간격을 일정하게 해줍니다.
// spaceBetween 은 스크린에 상 중 하 에 딱 붙어서 배치하게 됨
// spaceAround 은 스크린의 끝부분과 children 사이의 간격 모두 동일하게 위치합니다
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// crossAxisAlignment: CrossAxisAlignment.end,
// 가로방향으로 꽉 채워주기 위해선 stretch 해주면 각 container 에 상관 없이 가로 옆으로 꽉 차게 됩니다
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
width: 100,
height: 100,
color: Colors.red,
child: Text('Container 1'),
),
SizedBox(
height: 50.0,
),
Container(
width: 200,
height: 100,
color: Colors.yellow,
child: Text('Container 2'),
),
SizedBox(
height: 50.0,
),
Container(
width: 100,
height: 100,
color: Colors.green,
child: Text('Container 3'),
),
// 끝에 정렬을 맞게 width 를 최대한 크게 하라는 임의의 container 를 만들어 적용하면 오른쪽 끝으로 이동 합니다
Container(
width: double.infinity,
),
],
),
),
Row
- Container 를 가로 축으로 배열하는 위젯 설정 자세한 설정값은 위에 Column 에서 나온 속성들과 방향만 다르시 거의 동일하게 사용됩니다
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 100,
height: 100,
color: Colors.red,
child: Text('Container 1'),
),
SizedBox(
width: 30.0,
),
Container(
width: 100,
height: 100,
color: Colors.yellow,
child: Text('Container 2'),
),
SizedBox(
width: 30.0,
),
Container(
width: 100,
height: 100,
color: Colors.green,
child: Text('Container 3'),
),
],
),
),
🔶 🔷 📌 🔑
Reference
-
Flutter official site widget docs - https://flutter.dev/docs/development/ui/widgets-intro
-
Flutter Layout Cheat Sheet - https://medium.com/flutter-community/flutter-layout-cheat-sheet-5363348d037e
-
코딩셰프 - https://www.youtube.com/playlist?list=PLQt_pzi-LLfpcRFhWMywTePfZ2aPapvyl
Leave a comment