플러터:화면 전환(Drawer)
보이기
- 플러터:개요
- 플러터:실행
- 플러터:개념 잡기
- 권한 사용
- 위젯
- 플러터:DB연결
- 플러터:Firebase(미완)
- 플러터:MySQL(미완)
- 디자인
- 플러터:배포
- 플러터:배포(안드로이드)(미완)
- 플러터:참고자료
- 플러터:위젯
- 플러터:구글 AdMob(미완)
- 플러터:라이브러리
개요
앱 왼쪽(또는 오른쪽)에서 슬라이드하여 열리는 메뉴. Drawer는 보조 메뉴, 설정, 사용자 정보, 페이지 이동에 널리 사용된다.
하단 네비게이션바가 “항상 보이는 메뉴”라면, Drawer는 “필요할 때 여는 메뉴”라는 점이 다르다.
Drawer 기본 구조
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Drawer Demo',
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
static const List<Widget> _pages = [
Center(child: Text('첫 번째 화면', style: TextStyle(fontSize: 24))),
Center(child: Text('두 번째 화면', style: TextStyle(fontSize: 24))),
Center(child: Text('세 번째 화면', style: TextStyle(fontSize: 24))),
];
void _selectPage(int index) {
setState(() {
_selectedIndex = index;
});
Navigator.pop(context); // Drawer 닫기
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Drawer Demo"),
),
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(
child: Text(
"메뉴",
style: TextStyle(fontSize: 24),
),
),
ListTile(
title: Text("첫 번째 화면"),
onTap: () => _selectPage(0),
),
ListTile(
title: Text("두 번째 화면"),
onTap: () => _selectPage(1),
),
ListTile(
title: Text("세 번째 화면"),
onTap: () => _selectPage(2),
),
],
),
),
body: _pages[_selectedIndex],
);
}
}
이해를 위한 추가 설명
| 요소 | 설명 | 비고 |
|---|---|---|
| drawer: Drawer() | Scaffold에 Drawer를 추가하면 AppBar 왼쪽에 “햄버거 아이콘(≡)”이 자동 생성된다. | IconButton을 따로 만들 필요 없음. |
| DrawerHeader | 드로어 최상단 영역. 앱 제목, 프로필, 사용자 정보 등을 넣기에 적합하다. | backgroundColor 지정 가능. |
| ListTile | 메뉴 항목을 구성하는 기본 요소. onTap을 통해 화면 전환 처리. | BottomNavigationBar와 같은 방식(인덱스 변경)으로 동작 가능. |
| Navigator.pop(context) | Drawer를 닫는다. 메뉴 선택 시 Drawer가 열린 채로 남는 것을 방지한다. |
Drawer와 BottomNavigationBar 비교
| 항목 | Drawer | BottomNavigationBar |
|---|---|---|
| 목적 | 설정·보조 메뉴, 추가 기능 | 주요 화면 간 전환 |
| 표시 방식 | 필요할 때만 열림 | 항상 화면 아래에 있음 |
| 적합한 메뉴 수 | 많아도 괜찮음 | 보통 3~5개 |
| 접근 방식 | 햄버거 버튼 또는 슬라이드 | 언제든 탭 가능 |
의문
왜 Drawer에서는 Navigator.push 대신 index를 변경하는 방식이 많은가?
Drawer는 보통 앱의 주요 탭 전환을 담당하므로, 전체 레이아웃은 유지한 채 `body`만 교체하는 방식이 자연스럽다.
하지만 원한다면 Drawer에서도 push를 통한 화면 이동이 가능하다.
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (_) => SettingPage()),
);
}
둘 다 가능하며 상황에 따라 선택하면 된다.
Drawer는 오른쪽에서도 만들 수 있나?
가능하다.
endDrawer: Drawer(...)
이 경우 화면 오른쪽에서 슬라이드된다.
StatelessWidget으로 만들 수 없나?
Drawer가 선택한 메뉴에 따라 `body`를 바꾸려면 상태(index)를 유지해야 하므로 일반적으로 StatefulWidget이 필요하다.
내부 Navigator를 별도로 구성하면 Stateless로도 구현은 가능하지만 일반 구조에서는 잘 사용되지 않는다.
결론
- Drawer는 “필요할 때 여는 메뉴”
- BottomNavigationBar는 “항상 보이는 메뉴”
- 구현 원리는 동일 → 메뉴 선택 시 상태를 변경하여 body를 교체
- 보조 메뉴, 설정, 사용자 정보, 페이지 전환 등에 널리 사용됨