Drawer class
애플리케이션의 탐색 링크를 표시하기 위해 Scaffold 의 가장자리에서 수평으로 슬라이드 되는 Material Design 패널입니다.
이 구성 요소에는 NavigationDrawer 라는 Material 3 버전이 있는데 , 이는 Material 3에 맞게 구성된 애플리케이션에 더 적합합니다( ThemeData.useMaterial3 참조 ).
공식 문서 코드
페이지가 많아지고 기능이 많아지는데 그것을 공통화면에서 그 페이지들로 넘어가게 하려면 가장 좋은 방법은 무엇일까? 당연하게도 메뉴를 제작하여 메뉴에서 이동하게 만드는 것이다. 그 메뉴는 상단에 위치해 있는 앱 바가 될 수도 있고 하단에 위치해 있는 내비게이션바가 될 수도 있다. 하지만 이번에 알아볼 것은 흔히들 사용하는 형식이다. 메뉴버튼을 누르면 메뉴버튼이 위치해 있는 곳에서 패널이 튀어나와서 원하는 페이지로 이동할 수 있게 도와준다. 이러한 메뉴 패널을 아주 쉽게 만들어주는 위젯이 바로 Drawer 위젯이다.
이 Drawer 위젯은 앱의 측면에 위치하는 내비게이션 메뉴 패널을 구현할 때 사용된다. 일반적으로 앱의 왼쪽(또는 오른쪽)에 슬라이딩 방식으로 열리고, 다양한 메뉴 항목들을 포함해 사용자가 앱의 다른 페이지로 이동할 수 있도록 한다. 바로 알아보자.
하위 속성
| 속성명 | 타입 | 기본값 | 설명 |
| backgroundColor | Color? | null | Drawer의 배경색을 설정 |
| elevation | double? | 16.0 | 그림자 깊이를 설정해 z축에서의 높이를 지정 |
| shadowColor | Color? | null | 그림자 색상을 설정 |
| surfaceTintColor | Color? | Colors.transparent | 배경색에 겹쳐지는 표면 틴트 색상 |
| shape | ShapeBorder? | null | Drawer의 테두리 모양을 정의 |
| width | double? | 304.0 | Drawer의 너비를 설정 |
| child | Widget? | null | Drawer 내부에 표시할 콘텐츠 |
| semanticLabel | String? | MaterialLocalizations.drawerLabel | 접근성 기술에서 Drawer를 설명하는 라벨 |
| clipBehavior | Clip? | Clip.none 또는 Clip.hardEdge | shape이 있을 때 잘리는 방식 지정 |
일단 이 위젯은 사용하기 정말 간단하다. 놀랍게도 Scaffold 안에 그냥 이거 쓰라고 전용 파라미터가 구비되어 있다 ㄷㄷ
Scaffold(
drawer: Drawer(),
)
이미 이렇게만 해줘도 메뉴 패널 생성은 끝났다.
기본은 왼쪽이지만 오른쪽에서도 나오게 하고 싶으면 그냥 endDrawer 속성을 사용해 주면 된다.
Scaffold(
endDrawer: Drawer(),
)
또한 drawer 혹은 endDrawer 파라미터를 사용 시 기본적으로 AppBar 위젯을 사용하면 그 위치에 맞게 메뉴 아이콘이 생성이 되어 있다. 그리고 그러한 메뉴 아이콘을 클릭하면 메뉴 패널이 나오게 된다.
Scaffold(
appBar: AppBar(),
drawer: Drawer(),
endDrawer: Drawer(),
)

그냥 화면을 스와이프 해서 메뉴 패널이 나오면 좋겠지만 안탑깝게 도 그러한 기능은 없다.
여기서 주의해야 할 점은 Drawer 은 오직 최상위 Scaffold 안에서만 거의 동작하기 때문에 위젯 안에 Drawer 를 배치하고 싶다고 Scaffold 를 또 배치해서 넣는다고 해도 동작하지 않는다.
암튼 그렇다면 이 패널을 여는 방법은 또 뭐가 있을까? 가장 보편적인 방법으로는 글로벌 키를 사용하여 Scaffold 의 context 를 받아와 여는 방법이 있다.
먼저 사용할 key, 글로벌 키를 만들어준다.
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
이제 이 키를 Scaffold 에 넣어준다.
Scaffold(
key: _scaffoldKey,
이렇게 key 를 넣어줬다면 이제 사용가능해지게 되는데 원래 Drawer 을 여는 코드 자체는 아래와 같다.
Scaffold.of(context).openDrawer();
(영상을 보면 이렇게 사용하라고 나와있는데 실상 예제 코드를 보면 그냥 글로벌 키를 사용하는 모순적인 모습을 볼 수 있다.)
저 코드도 맞아 보이지만 동작하지 않는 원인이 있다. 바로 Scaffold.of(context)가 실행되는 시점의 context가 Scaffold 내부에 직접 연결되지 않았기 때문이다. 즉 Scaffold 의 context 를 가져오지 못하여서 실행해 보면 아무 동작도 하지 않는다.
암튼 위 코드에서 가져올 건 openDrawer 함수 밖에 없겠다. 오른쪽에서 열리게 해놨다면 openEndDrawer 쓰면 된다.
onPressed: () {
_scaffoldKey.currentState!.openDrawer();
},
이 코드는 현재 scaffoldKey 를 가져오고 있는데 아까 위에서 만들었다시피 GlobalKey<ScaffoldState> 이런 타입을 가지고 있다.
이건 Scaffold 의 상태에 접근하기 위하여 사용되는 키인데 이걸로 일단 Scaffold 에 접근한 후 currentState 로 위젯에 연결된 상태 객체(ScaffoldState)를 가져오게 된다.
이제 마지막으로 상태 다 가져왔으니까 openDrawer 하면 잘 패널이 열리게 될 것이다.
여기까지 Drawer 위젯의 사용법이었다. 그렇다면 이제 안을 어떻게 꾸밀지 알아보자.
Drawer 은 하위 속성, 파라미터로 child 를 갖고 있는데 보통은 여기다가 ListView 를 사용하여 배치한다.
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(child: Text('타이틀')),
ListTile(title: Text('타일1'),),
ListTile(title: Text('타일2'),),
ListTile(title: Text('타일3'),),
],
),
),
보통은 이런 식으로 사용하게 된다. ListView 안에 ListTile 들로 아이템을 배치해 주고 제목 같은 건 DrawerHeader 를 사용하여 머테리얼 디자인에 맞게 배치해 줄 수 있다.

이제 여기서 더 파라미터를 알아보자면
backgroundColor: Colors.blue,
backroundColor 를 사용해서 배경색을 바로 먹여줄 수 있다.

사실 근데 나는 child 안에다가 Column 배치한 다음에 커스텀으로 디자인할 거 같긴 하다.
암튼 이렇게 Drawer 위젯에 대해서 간단하게 알아보았다. 이 위젯은 이런 되게 좋은 기능인데 반해 사용하기 진짜 엄청 쉬우니까 꼭 사용해 보길 바란다. 도움이 되었길 바라며 마치겠다.