🕶️ State에 관한 고찰
Flutter에서 Widget은 꼭 필요한 요소이다. Flutter에서 UI 구성요소 == Widget이라고 보아도 무방하다. 모든 widget은 자신이 stateless widget인지 stateful widget인지 결정을 해줘야 한다.
일단 Widget의 종류를 알기 위해 가장 먼저 알아야 할 선수 지식이 있다. 바로 State(상태)이다.
예를 들어 타이머 앱이 있다고 생각 하자. 타이머 앱에 있는 StopWatch는 1초마다 화면을 전환 해줘야 한다.
class timerPage extends StatefulWidget {
const timerPage({Key? key}) : super(key: key);
@override
_timerPageState createState() => _timerPageState();
}
class _timerPageState extends State<timerPage> {
Timer timer = Timer(Duration(milliseconds: 1), () {});
int countTime = 150001;
bool isRunning = false;
bool isRest = false;
@override
void dispose() {
timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SizedBox.expand(
child: Container(
color: Color(isRest?0xff2E3C7E:0xffffff),
child: _buildBody()
)
);
}
//코드 생략
개발 당시 Page 단위로 제작 했기 때문에, Class의 이름은 timerPage이며 extends로 StatefulWidget을 사용 하고 있다.
시간의 값이 바뀌는 것 즉 State가 변화하기 때문에 유저에게 보이는 UI값도 변화합니다. 이럴 때 Stateful Widget을 사용해야 합니다.
1. Stateless Widget
직역하면 상태가 없는 위젯이라는 의미로, 화면상엔 존재하나 실시간으로 데이터가 변화하지 않는 상태. 즉 상태가 변하지 않는 위젯들을 의미합니다.
2. Stateful Widget
직역하면 상태를 가지는 위젯이라는 의미로, BackEnd 단에서 데이터가 변하거나, 사용자의 행동에 따라 값이 바뀌는 위젯을 의미 한다. 위 영상의 시간을 표시하는 페이지 전체가 Stateful Widget이다.
Life Cycle
Stateful Widget
- Widget에서 상태를 초기화하기 위해 initState를 호출한다. (build 전 초기화 단계)
- initState()로 초기화 되면 build()가 호출 되고 Widget이 화면에 그려지게 된다.
- Stateful Widget은 setState라는 특별한 함수를 가지고 있는데, setState 함수를 호출하게 되면 build 함수를 재 호출하게 된다. (setState란 state 또는 데이터가 변화하여 UI단에서 화면이 변화되어야 할 때 사용되는 함수이다)
- 마지막 dispose() 를 통해 UI에서 사라지게 된다.
Stateless Widget
- 변화될 State 또는 데이터가 존재하지 않기 때문에 build 후 UI 단에서 변화하지 않는다.
- 마지막 dispose() 를 통해 UI에서 사라지게 된다.
🕶️ Widget에 관한 고찰
Widget Tree
Flutter의 Widget 개념 중 매우 중요하다고 볼 수 있는 Tree이다.
Flutter 앱은 수많은 Widget들이 겹겹이 쌓여있는 Tree구조를 가지고 있다.
트리 구조엔 부모 자식간의 관계가 성립되는데, 해외 레퍼런스에선 부모 위젯을 Container Widget이라고 칭하기도 한다. (자식을 감싸고 있는 위젯이라 컨테이너 위젯이라고 부르는 것으로 추정)
- MyApp은 최상위 위젯으로 프로젝트 이름을 담당한다.
- MaterialApp이 실질적으로 모든 위젯의 조상 또는 부모 위젯이다. 이 위젯을 이용하여야 모든 플러터 위젯을 사용 할 수 있다. (Material 디자인을 따른다)
- 다양한 App들이 있는데 부모 Widget의 build가 완료되려면 자식 Widget의 build가 완료 되어야 한다.
🔍 UI Structure Widget
1. Material App Widget
앱 전반의 UI, Navigator 설정 등등 모바일 앱에 필요한 기능들을 제공하는 위젯 WidgetsApp이 있으나, WidgetsApp을 사용하기 위해선 직접 더 구현하고 작업해야 하기 때문에, Material Design에서 제공하는 MaterialApp과 IOS 디자인을 제공하는 CupertinoApp이 있다.
return MaterialApp(
title: 'Timer App',
debugShowCheckedModeBanner: false,
theme: CustomTheme(),
home: PageContainer(settings: settings),
);
앱의 title, theme 및 전반적인 앱 설정을 할 수 있는 Widget이다.
2. Scaffold Widget
MaterialApp Widget이 앱의 설정과 기능을 제공하는 위젯이였다면, Scaffold Widget은 앱의 구조를 만드는 역할을 한다.
AppBar
- AppBar는 앱 상단의 바를 의미 한다.
- Appbar의 특성, 뒤로 갈 수 있는 화면이라 판단 되면 앱의 Navigator는 자동으로 백 버튼을 추가 한다.
- 보통 UI/UX로 보았을 때 앱의 로고나, 앱의 아이덴티티를 나타내는 Leading/Title Section이 있다.
- actions로 다른 페이지로 push 될 수 있는 아이콘들을 넣었다. (게시물 추가, 좋아요 확인, DM)
Body
- 앱의 내용 부분을 담당하는 곳이다.
- 상단 AppBar와 하단 Bottom Widget을 제외한 UI로서 앱의 전체적인 내용 부분을 담당한다.
Bottom Navigation Bar
- 마지막 Structure인 바텀 네비게이션 바이다.
- 이름에서 볼 수 있는 것 처럼 다른 페이지로 네비게이션 할 수 있도록 기능이 맞춰져 있다.
Drawer
- 한쪽 모서리에서 미끄러지듯 등장 하는 요소로 메뉴를 구현할 때 사용 된다.
🔍 Theme & Style
보통의 웹 개발 프레임워크와 같이, PrimaryColor, AccentColor 같이 화면에서 자주 사용하는 색 값을 저장 할 수 있도록 Flutter에서도 ThemeData라는 객체를 생성 하여 Theme 위젯에 할당 할 수 있다.
색 관련 property
- brightness (밝기 조정)
- primarySwatch (Material Design 견본 색상 설정)
- primaryColor
- accentColor
이외에도 20개 이상의 property가 존재 한다.
ThemeData({
Brightness brightness,
VisualDensity visualDensity,
MaterialColor primarySwatch,
Color primaryColor,
Brightness primaryColorBrightness,
Color primaryColorLight,
Color primaryColorDark,
Color accentColor,
Brightness accentColorBrightness,
Color canvasColor,
Color shadowColor,
Color scaffoldBackgroundColor,
Color bottomAppBarColor,
Color cardColor,
Color dividerColor,
Color focusColor,
Color hoverColor,
Color highlightColor,
Color splashColor,
InteractiveInkFeatureFactory splashFactory,
Color selectedRowColor,
Color unselectedWidgetColor,
Color disabledColor,
Color buttonColor,
ButtonThemeData buttonTheme,
ToggleButtonsThemeData toggleButtonsTheme,
Color secondaryHeaderColor,
Color textSelectionColor,
Color cursorColor,
Color textSelectionHandleColor,
Color backgroundColor,
Color dialogBackgroundColor,
Color indicatorColor,
Color hintColor,
Color errorColor,
Color toggleableActiveColor,
...);
Flutter MediaQuery
- Flutter의 layout 크기 문제는 논리 픽셀(logical pixel) 단위를 사용한다.
- 사이즈 크기 퍼센트(%)를 사용 할 수 없기 때문에 MediaQuery Widget을 사용하여 화면 크기를 알아야 함.
final width = MediaQuery.of(context).size.width;
앱을 실행하는 물리적 디바이스의 정보를 얻거나, 디바이스를 제어할 때 Media Query를 사용한다. 예로,
- 사용자의 휴대폰 해상도, 사이즈를 확인 할 경우
- 현재 휴대폰이 세로방향인지 가로방향인지 확인 할 경우
- 사용자가 화면을 확대 했을 경우
등이 있다.
레퍼런스
'Flutter 개발 > Flutter 개념' 카테고리의 다른 글
[Flutter] 오픈소스 패키지 사용해보기 (0) | 2022.03.08 |
---|---|
[Flutter] Flutter에 관한 고찰 (0) | 2022.02.26 |