Flutter를 시작하는데 UI, Widget이 이해가 잘 가지 않아 codelab의 내용을 계속 보고 있다.
https://docs.flutter.dev/development/ui/layout
한글로 된 문서는 없는데 최대한 정리를 해보려고 한다.
정리하다 보니 생각보다 이해가 가기 시작했다.
(한글화 프로젝트 환영입니다!)
중요 포인트
- Widget은 UI를 구성하는 클래스다.
- Widget은 layout과 UI element에 사용된다.
- Compose simple widget은 유연한 widget을 만들기 위해 사용한다.
Flutter layout의 가장 중요한 정수이자 메커니즘은 widget이다. Flutter에서는 거의 모든 것이 Widget이고 심지어 layout 모델들도 widget이다.
해당 codelab에서 진행하는 UI의 widget tree이다.
Container는 자식 클래스를 customize 해서 가지기 위한 widget이다. padding, margin, border, background color, name을 지정해줄 수 있다.
이 예제에서는 Text위젯이 Container에 들어가긴 했는데 margin을 주기 위한 목적으로 사용되었다. 최상위 Row는 row에 대해 padding을 주기 위해 사용되었다.
나머지 UI는 properties로 제어된다. Icon의 색상은 color property를 사용한다. Text.style property는 font나 color, weight 등을 설정한다. Column과 row는 각 내부 children을 얼마나 가질지와 horizontally인지, vertically인지 설정하고 각 children이 얼마나 공간을 차지할지 설정한다.
Lay out a widget
(왜 Lay out인지 모르겠다. Layout이 더 맞지 않나... 검색해보니 Lay out은 동사로 쓰일 때 저렇게 사용한다.)
이 항목에서는 simple widget을 보여주고 만드는 법을 알려준다.
모든 코드는 simple Hello World app에서 시작합니다.
visible widget 만들기
(이 글을 작성하면서 코드블럭의 단축키는 맥 기준 command + option + , 라는걸 알았다.)
Text widget
Text('Hello World');
Image widget
Image.asset(
'images/lake.jpg',
fit: : BoxFit.cover,
),
Icon widget
Icon(
Icons.star,
color: Colors.red[500],
),
layout widget에 visible widget 추가하기
모든 layout widget은 아래와 같은 특성을 가진다.
- 하나의 [child] property는 하나의 child(예를 들어 Center나 Container 같은)만을 가진다.
- 하나의 [children] property는 widget리스트를 가진다(Row, Column, ListView, Stack 등..)
Text widget이 Center Widget에서 사용되는 예시
const Center(
child: Text('Hello World'),
),
Flutter app은 wdiget이고 대부분의 widget은 build() 메서드를 가진다.
Material apps
Materail app에서 Scaffold widget을 사용할 수 있다. 기본적인 백그라운드 색상과 배너, 여러 가지를 추가할 수 있는 snack bars, bottom sheets 등을 제공한다. Center widtet을 [body] property에 바로 넣을 수 있다.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter layout demo',
home: Scaffold(
appBar: AppBar(
title: const Text('Flutter layout demo'),
),
body: const Center(
child: Text('Hello World'),
),
),
);
}
}
Non-Material apps
non-Material app에서는 center widget을 build 메서드에 추가할 수 있다.
기본적으로 non-Material app에는 AppBar와 title, background color가 포함되어있지 않다. 만약에 넣고 싶으면 직접 build 해야 한다.
Lay out multiple widgets vertially and horizontally
layout 패턴에서 가장 일반적으로 사용하는 건 수직으로 놓거나 가로로 놓는 것이다. Row widget을 사용해서 가로로 할 수 있고 Column widget을 이용해서 세로로 할 수 있다.
What's the point?
- Row와 Column은 가장 많이 사용되는 layout pattern이다.
- Row와 Column은 child widget의 list를 가진다.
- 하나의 child widget은 Row나 Column, 다른 complex widget이 될 수 있다.
- Row나 Column의 각 children에 대해 명시하고 각각 세로와 가로를 가질 수 있다(?)
- 각각의 child widget을 늘리거나 줄일 수 있다.
- child widget의 Row나 Column이 차지하는 범위를 조정할 수 있다.
Flutter에서 row나 column을 만들기 위해 Row나 Column widget에 children widget을 list로 붙인다.
각 child는 순서대로 row와 column이 된다. 아래 예시는 중첩된 row나 column의 사용에 대해 보여준다.
아래 layout은 Row로 구성되어있다. row는 2개의 children을 가진다(왼쪽 column과 오른쪽 이미지 영역)
왼쪽 column widget은 다시 row와 column이 중첩되어있다.
밑에 나오지만 이 layout 코드를 여기서 구현하고 확인할 수 있다https://docs.flutter.dev/development/ui/layout#nesting-rows-and-column
중요!
Row와 Column widget은 horizontal과 vertical layout을 만드는 가장 기본이 되는 widget이다. 이러한 low-level widget들은 customization을 최대로 지원한다. Flutter 또한 특별하게 higher level widget들은 당신이 원할만한 것들을 미리 마련해두었다. 예를 들어 Row보다 ListTile을 더 선호할 것이고 Column을 사용하는 것보다 ListView를 더 선호할 것이다.
더 자세한 정보는 여기서 찾아보자.Common layout widgets
Aligning widgets
많은 row나 column, 각 children을 정렬하기 위해 mainAxisAlignment와 crossAxisAlignment properties를 사용한다.
Row의 main axis는 가로 방향이고 cross axis는 세로 방향으로 진행된다. Column에서는 그와 반대로 main axis는 세로로 진행되고 cross axis는 세로로 진행된다.
MainAxisAlignment와 CrossAxisAlignment는 각 정렬을 위해 많은 상수를 제공하고 있다.
아래 예시에서는 100pixel 이미지 3개가 있다. 전체 화면은 당연히 300pixel보다 크다. 이럴 때 spaceEvenly 상수를 사용하면 균등하게 분배를 해준다.
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.asset('images/pic1.jpg'),
Image.asset('images/pic2.jpg'),
Image.asset('images/pic3.jpg'),
],
);
Sizing widgets
layout이 device대비 너무 크면 잘리거나 검은 줄이 생긴다. 이걸 맞추기 위해 Expanded widget을 사용하자.
각 box에 맞춰준다.
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
다 균등하게 주지 않고 하나에 대해 특정 비율만큼 조절을 할 수도 있다.
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Image.asset('images/pic1.jpg'),
),
Expanded(
flex: 2,
child: Image.asset('images/pic2.jpg'),
),
Expanded(
child: Image.asset('images/pic3.jpg'),
),
],
);
Packing widgets
기본적으로 row와 column은 main axis에서 가능한 만큼 영역을 차지한다. 만약 각 children의 요소끼리 가깝게 붙여야 한다면 mainAxisSize.min을 사용해보자.
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
Icon(Icons.star, color: Colors.green[500]),
const Icon(Icons.star, color: Colors.black),
const Icon(Icons.star, color: Colors.black),
],
)
양이 생각보다 많은 듯 적은 듯한데 다음 글에서 다 정리가 될 것 같다. 그러고 나면 나도 이제 만들기 시작해야겠다.
'dart > Flutter' 카테고리의 다른 글
우당탕탕 Flutter 학습기 - System tray(2) (0) | 2022.04.01 |
---|---|
에러 : Target of URI doesn't exist 'package:flutter/material.dart' (1) | 2022.03.31 |
우당탕탕 Flutter 학습기 - System tray(1) (0) | 2022.03.31 |
Layouts in Flutter 정리 (2) (0) | 2022.03.30 |
정말 잠깐 Flutter tutorial을 따라해본 후기 (0) | 2021.03.28 |