Study Record

[Flutter] 슬라이드 메뉴(Drawer) 본문

Flutter/widget

[Flutter] 슬라이드 메뉴(Drawer)

초코초코초코 2023. 3. 17. 17:40
728x90

Drawer 

Dawer 위젯은 햄버거 아이콘을 누르면 슬라이드 메뉴가 나오는 기능을 쉽게 구현해 준다. Scaffold 인자 중 drawer 에 Drawer 위젯을 넣고 appBar 인자를 채우면 자동으로 앱바에 햄버거 아이콘이 추가되면서 Drawer 를 열고 닫기를 조절할 수 있다.

 

기본 모양은 다음과 같다. Drawer 의 child 로 슬라이드 메뉴의 위젯을 넣어준다.

Scaffold(
  appBar: AppBar(title: const Text("Drawer")),
  drawer: Drawer(
    backgroundColor: Colors.deepPurple,
    child: ListView(
      children: [
        const DrawerHeader(
          child: Text("Drawer Header", style: TextStyle(color: Colors.white)),
        ),
        ...List.generate(
          15,
          (index) => ListTile(
            onTap: () {},
            title: Text("item $index", style: TextStyle(color: Colors.black87)),
          ),
        ),
      ],
    ),
  ),
  body: Container(),
)

 

 

😶 Drawer 열고 닫기

슬라이드를 사용하거나 햄버거 아이콘을 클릭하는 것외에 코드로 Drawer 를 열고 닫을 수 있다.

// Drawer 열기
Scaffold.of(context).openDrawer();

// Drawer 닫기
Navigator.of(context).pop();

주의해야 할 점은 Drawer 를 open 할 때 Scaffold 와 같은 위젯에 있으면 Scaffold.of(context) 에서 Scaffold 를 찾을 수 없다고 나온다.

 

 

예시 )

import 'package:flutter/material.dart';

void main() => runApp(MaterialApp(home: MyAppView()));

class MyAppView extends StatefulWidget {
  const MyAppView({Key? key}) : super(key: key);

  @override
  State<MyAppView> createState() => _MyAppViewState();
}

class _MyAppViewState extends State<MyAppView> {
  int? itemValue;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("Drawer")),
      drawer: MyDrawerView(
        onTap: (int value) {
          setState(() {
            itemValue = value;
          });
          Navigator.of(context).pop();
        },
      ),
      body: BodyView(itemValue: itemValue),
    );
  }
}

typedef OnListTap = void Function(int value);

class MyDrawerView extends StatelessWidget {
  final OnListTap onTap;
  const MyDrawerView({Key? key, required this.onTap}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Drawer(
      backgroundColor: Colors.deepPurple,
      child: ListView(
        children: [
          const DrawerHeader(
            child: Text("Drawer Header", style: TextStyle(color: Colors.white)),
          ),
          ...List.generate(
            15,
            (index) => ListTile(
              tileColor: Colors.white,
              onTap: () {
                onTap(index);
              },
              title:
                  Text("item $index", style: TextStyle(color: Colors.black87)),
            ),
          ),
        ],
      ),
    );
  }
}

class BodyView extends StatelessWidget {
  final int? itemValue;
  BodyView({Key? key, required this.itemValue}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        Text(
          itemValue == null ? "item 선택 없음" : "$itemValue",
          textAlign: TextAlign.center,
        ),
        const SizedBox(height: 16.0),
        ElevatedButton(
            onPressed: () {
              Scaffold.of(context).openDrawer();
            },
            child: Text("네비게이션 바 열기")),
      ],
    );
  }
}

 

 

 

😶 Drawer 인자

backgroundColor 는 Drawer 의 바탕색을 의미하고 child 는 Drawer 에 들어갈 위젯, shape 는 모서리 부분을 꾸밀 수 있다.

Drawer({  
  Key? key,
  Color? backgroundColor,
  double? elevation, 
  ShapeBorder? shape,  
  double? width,  
  Widget? child, 
  String? semanticLabel,
})

 

 

728x90