Flutter/2.0

Flutter에서 Drawer 메뉴 만들기

lgvv 2021. 8. 10. 16:50

Flutter에서 Drawer 메뉴 만들기

 

이번 시간에는 AppBar의 햄버거(☰) 버튼을 클릭했을 때 열리는 Drawer 메뉴를 만들어보자.

아래 이미지를 보면, AppBar 왼쪽의 아이콘을 누르면 사이드 패널이 열리는 UI를 말한다.

 

 

Drawer를 사용할 때 주의할 점

Drawer는 내부적으로 AppBar의 왼쪽 영역(leading 부분)을 자동으로 제어하기 때문에 수동으로 지정하면 충돌이 발생.

// ❌ 아래처럼 leading에 IconButton을 추가하면 Drawer가 작동하지 않는다!
leading: IconButton(
  icon: Icon(Icons.menu),
  onPressed: () {
    print("menu button clicked");
  },
),

 

 

 

 

Drawer 샘플 스크린샷 1

 

샘플 스크린샷

 

 

Drawer 샘플 코드 1

 

drawer 속성

  • Scaffold의 drawer 속성은 화면 왼쪽에서 열리는 사이드 패널 UI를 정의
  • Drawer 안에는 보통 ListView를 사용해서 여러 메뉴를 세로로 나열

 

padding: EdgeInsets.zero 상단 잘림 방지용

  • 이걸 빼면 Drawer의 헤더가 AppBar 아래에 겹쳐서 보임.

 

import 'package:flutter/material.dart'; // 데스크탑, 앱 등에 고루 UI를 적용할 수 있게 해주는 구글이 제공해주는 패키

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      // 실질적으로 모든 앱을 감싸고 있다.
      title: 'Appbar', // 앱을 총칭하는 이름 -> 스마트 폰 앱에서 최근 사용한 앱 보여줄 때의 이름
      theme: ThemeData(primarySwatch: Colors.red // 특정색의 응용들을 기본 색상으로 지정해서 사용하겠
          ),
      home: MyPage(), // home은 앱이 실행될 때 가장먼저 보여주는 페이
    );
  }
}

class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar icon menu'),
        elevation: 0.0,
        actions: [
          // action 속성은 복수의 아이콘 버튼 등을 오른쪽에 배치할 때
          IconButton(
            // 간단한 위젯이나 타이틀들을 앱바의 왼쪽에 위치시키는 것을 말함
            icon: Icon(Icons.shopping_cart), // 아이콘
            onPressed: () {
              // 버튼을 눌렀을 때
              print("shopping_cart is clicked");
            },
          ),
          IconButton(
            // 간단한 위젯이나 타이틀들을 앱바의 왼쪽에 위치시키는 것을 말함
            icon: Icon(Icons.search), // 아이콘
            onPressed: () {
              // 버튼을 눌렀을 때
              print("search is clicked");
            },
          )
        ],
      ),
      drawer: Drawer( // 햄버거 버튼으로 사이드바 만드는 코드
        child: ListView( // 리스트 뷰 통해서 넣어야 해
          padding: EdgeInsets.zero, // 이 코드 중요하다. 이거 없으면 상단 부분이 짤리게 나옴
          children: [
            UserAccountsDrawerHeader( // Drawer의 헤더쪽에 넣을 코드
              currentAccountPicture: CircleAvatar( // 헤더에 넣어줄 이미지
                backgroundImage: AssetImage('assets/bbanto.png'),
                backgroundColor: Colors.white,
              ),
              accountName: Text('bbanto'), // @require 로 필수 : 이름
              accountEmail: Text('testEmail@test.com'), // @require 로 필수 : 이메일
              onDetailsPressed: () {
                print('Header is clicked');
              },
              decoration: BoxDecoration( // 데코레이션이라고 해서 박스를 꾸미기
                  color: Colors.redAccent[200],
                  borderRadius: BorderRadius.only( // 하단에만 적용하겠다.
                      bottomLeft: Radius.circular(40.0),
                      bottomRight: Radius.circular(40.0))),
            ),
          ],
        ),
      ),
    );
  }
}

 

 

 

 

Drawer 샘플 스크린샷 2

 

 

 

좀 더 자세히 볼 부분

3가지 부분을 좀 더 자세히 볼 것

  1. UserAccountsDrawerHeader다른 계정 사진 추가하기
  2. ListTile을 이용해 Drawer 내부 메뉴 구성하기
  3. onTap, leading, trailing의 역할 이해하기

 

샘플 코드 2

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Appbar',
      theme: ThemeData(primarySwatch: Colors.red),
      home: MyPage(),
    );
  }
}

class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AppBar icon menu'),
        elevation: 0.0,
        actions: [
          IconButton(
            icon: Icon(Icons.shopping_cart),
            onPressed: () {
              print("shopping_cart is clicked");
            },
          ),
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              print("search is clicked");
            },
          ),
        ],
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            UserAccountsDrawerHeader(
              currentAccountPicture: CircleAvatar(
                backgroundImage: AssetImage('assets/bbanto.png'),
                backgroundColor: Colors.white,
              ),
              otherAccountsPictures: [
                CircleAvatar(
                  backgroundImage: AssetImage('assets/chef.png'),
                  backgroundColor: Colors.white,
                ),
              ],
              accountName: Text('bbanto'),
              accountEmail: Text('testEmail@test.com'),
              onDetailsPressed: () {
                print('Header is clicked');
              },
              decoration: BoxDecoration(
                color: Colors.redAccent[200],
                borderRadius: BorderRadius.only(
                  bottomLeft: Radius.circular(40.0),
                  bottomRight: Radius.circular(40.0),
                ),
              ),
            ),
            ListTile(
              leading: Icon(Icons.home, color: Colors.grey[850]),
              title: Text('Home'),
              trailing: Icon(Icons.add),
              onTap: () {
                print('home is clicked');
              },
            ),
            ListTile(
              leading: Icon(Icons.settings, color: Colors.grey[850]),
              title: Text('QnA'),
              trailing: Icon(Icons.add),
              onTap: () {
                print('settings is clicked');
              },
            ),
            ListTile(
              leading: Icon(Icons.question_answer, color: Colors.grey[850]),
              title: Text('Question'),
              trailing: Icon(Icons.add),
              onTap: () {
                print('question_answer is clicked');
              },
            ),
          ],
        ),
      ),
    );
  }
}