ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • UI Development Exam - CircleAvartar, DrawerHeader
    DEVELOPMENT/FLUTTER 2022. 1. 23. 17:10

    현대적인 SW의 UI에서는 메뉴바를 어떻게 세련되게 표현하는지의 여부도 매우 중요해 보입니다. 앱스토어 리뷰를 보아도 세련된 화면 구성, 사용자 경험 등에 대한 불평불만과 칭찬이 번갈아 등장하는 것으로 보아 요즘 SW는 디자이너의 역량이 매우 중요하더라구요.

     

    EndDrawer

     

    서랍이라는 뜻을 가진 Drawer는 반응형 웹과 스마트 디바이스에서 사용하는 Menu입니다. 三(햄버거 모양이라고도 불리더라구요) 모양의 아이콘을 클릭하면 애플리케이션의 메뉴가 나타나는 것이 Drawer에 대한 기본적인 사용자 경험입니다.

     

    기본적으로 안드로이드 디바이스에서 Drawer는 Appbar 왼쪽에 위치하는데,  iOS는 이와는 또 다른지 플러터는 Drawer와 EndDrawer 두 가지 Drawer를 제공합니다. 차이는 Drawer 아이콘의 위치와 Menu가 열리는 방향입니다.(왼쪽에서 오른쪽, 오른쪽에서 왼쪽)

    기본적인 코드는 다음과 같습니다.

     

    import 'package:flutter/material.dart';
    import 'package:my_profile/appbar/my_app_bar.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          endDrawer: Drawer(
          ),
          appBar: MyAppBar(),
          body: Center(
            child: Column(
            )
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }

     

    Drawer(EndDrawer)는 AppBar에 표시되지만, AppBar의 속성으로 설정하지는 않습니다. (약간의 충격.. 왜 이렇게 했지? 하는) Scaffold의 속성으로 설정하니 헷갈리지 말아야겠습니다.

     

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    class MyAppBar extends StatefulWidget with PreferredSizeWidget{
      @override
      Size get preferredSize => const Size.fromHeight(50);
    
      @override
      _MyAppBarState createState() => _MyAppBarState();
    }
    
    class _MyAppBarState extends State<MyAppBar> {
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: AppBar(
            backgroundColor: Colors.white, // AppBar 배경색
            elevation: 0.5, // AppBar 하단 그림자 처리
            centerTitle: true, // 타이틀 글자 중앙 배치
            iconTheme: IconThemeData(color: Colors.blueAccent), // 아이콘 테마 색상 통일을 위한 배치, Drawer 아이콘은 별도의 색상 변경 방법이 없어 어쩔 수 없이 커스텀 아이콘 테마로 작업해야 함
            leading: Icon(CupertinoIcons.back), // 왼쪽에 배치하는 버튼
            title: Text('My Profile App', style: TextStyle(color: Colors.black),), // 타이틀 글자
          ),
        );
      }
    }

     

    배경을 흰 색으로 처리하니 Drawer의 메뉴가 안 보입니다. 아이콘 색상까지 흰 색으로 설정해서 이런 결과가 나오게 되는데, 아이콘 테마를 사용해서 통일된 아이콘 색상을 줄 수 있습니다.

     

    iconTheme: IconThemeData(color: Colors.blueAccent)

     

    AppBar의 전체 코드는 아래와 같습니다. 이번에도 AppBar 높이 설정하는 함수를 까먹었다는...-_-;

     

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    
    class MyAppBar extends StatefulWidget with PreferredSizeWidget{
      @override
      Size get preferredSize => const Size.fromHeight(50); // AppBar 높이 설정
    
      @override
      _MyAppBarState createState() => _MyAppBarState();
    }
    
    class _MyAppBarState extends State<MyAppBar> {
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: AppBar(
            backgroundColor: Colors.white, // AppBar 배경색
            elevation: 0.5, // AppBar 하단 그림자 처리
            centerTitle: true, // 타이틀 글자 중앙 배치
            iconTheme: IconThemeData(color: Colors.blueAccent), // 아이콘 테마 색상 통일을 위한 배치, Drawer 아이콘은 별도의 색상 변경 방법이 없어 어쩔 수 없이 커스텀 아이콘 테마로 작업해야 함
            leading: Icon(CupertinoIcons.back), // 왼쪽에 배치하는 버튼
            title: Text('My Profile App', style: TextStyle(color: Colors.black),), // 타이틀 글자
          ),
        );
      }
    }

     

     

    Drawer에 별도 내용을 넣지 않았기 때문에 아직은 비어있는 화면만 나옵니다. 현재까지 작성한 코드를 약간 수정해서 Drawer 클래스를 따로 만들어야겠습니다.

     

    Drawer 위젯은 상단에 DrawerHeader나 UserAccountsDrawerHeader를 설정할 수 있는데 왠지 느껴지는 Google의 사려깊음(?)을 느끼게 됩니다. 프로토타입 제작 시에 빠르게 제작할 수 있어 편할 것 같습니다. 하지만 디자이너분들은 굳이 프로토타입을 사용하지 않을 것 같습니다.

     

    Drawer

     

    Drawer 위젯은 하나의 하위 위젯을 가질 수 있기 때문에 보통 ListView 위젯을 사용하여 여러 아이템을 표시합니다. 그리고 Header가 필요하면 ListView에 DrawHeader를 선언합니다.

    아.. 그리고 ListView에는 padding 속성을 설정할 수 있습니다. Padding 위젯을 만들지 않아도 되죠... 위젯 간 상속 관계가 어떻게 되는건지 헷갈립니다.

     

    import 'package:flutter/material.dart';
    
    class MyEndDrawer extends StatefulWidget {
      @override
      _MyEndDrawerState createState() => _MyEndDrawerState();
    }
    
    class _MyEndDrawerState extends State<MyEndDrawer> {
      @override
      Widget build(BuildContext context) {
        return Drawer(
          child: ListView(
            children: [
              DrawerHeader(
                decoration: BoxDecoration(
                  color: Colors.blueAccent,
                ),
                child: Text("Drawer Header")
              )
            ],
          ),
        );
      }
    }

     

     

    앗... DrawerHeader가 너무 높이가 큽니다. DrawerHeader는 높이 설정을 할 수가 없습니다. 고민하던 중 검색을 통해 해결책을 알아냈는데... 플러터 위젯 구성의 만능키 Container로 DrawerHeader를 감싸고 높이를 지정하면 Container의 높이에 맞춰 DrawerHeader가 설정되었습니다.

     

    import 'package:flutter/material.dart';
    
    class MyEndDrawer extends StatefulWidget {
      @override
      _MyEndDrawerState createState() => _MyEndDrawerState();
    }
    
    class _MyEndDrawerState extends State<MyEndDrawer> {
      @override
      Widget build(BuildContext context) {
        return Drawer(
          child: ListView(
            children: [
              Container(
                height: 50,
                child: DrawerHeader(
                  decoration: BoxDecoration(
                    color: Colors.blueAccent,
                  ),
                  child: Text("Drawer Header")
                ),
              )
            ],
          ),
        );
      }
    }

     

     

    decoration 속성에 BoxDecoration 속성을 추가하여 아래 그림과 같이 약간의 디자인적 기교를 부릴수도 있습니다.

     

    child: DrawerHeader(
      decoration: BoxDecoration(
        color: Colors.blueAccent,
        borderRadius: BorderRadius.only( // DrawerHeader의 모서리를 둥글게 처리하기
          bottomLeft: Radius.circular(30), // 왼쪽 아래 30만큼
          bottomRight: Radius.circular(30), // 오른쪽 아래 30만큼
        )
      ),
      child: Text("Drawer Header")
    ),

     

     

    UserAccountDrawerHeader

     

    이 위젯은 사용자 정보 표시에 필요한 템플릿이라고 할 수 있습니다. 현재 사용자 사진 및 이름, 이메일 주소, 이전 사용자 사진 등으로 이루어져 있습니다. 기본적인 코드들을 한 번 만들어보면서 기능을 알아봅시다.

     

    import 'package:flutter/material.dart';
    
    class MyAccountDrawer extends StatefulWidget {
      @override
      _MyAccountDrawerState createState() => _MyAccountDrawerState();
    }
    
    class _MyAccountDrawerState extends State<MyAccountDrawer> {
      @override
      Widget build(BuildContext context) {
        return Drawer(
          child: ListView(
            children: [
              UserAccountsDrawerHeader(
                currentAccountPicture: Image.network('https://www.stockvault.net/data/2016/02/20/184621/preview16.jpg'),
                accountName: Text('USER'),
                accountEmail: Text('admin@abc.def'),
                otherAccountsPictures: [
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                  Image.network('https://pixnio.com/free-images/2020/01/15/2020-01-15-18-48-29-1200x900.jpg'),
                ],
              ),
    
            ],
          ),
        );
      }
    }

     

     

    당연하겠지만.. 기본적으로 위젯들은 왼쪽 정렬입니다. 그리고 otherAccountPictures 속성의 경우 최대 3개의 사진까지만 입력이 가능하네요. 참고해야겠습니다. 그런데 사진들이 좀 멋스럽지가 않습니다. 카카오톡이나 인스타그램처럼 윈형 모양으로 사진이 표시되도록 설정하면 더 좋을 것 같습니다.

    그리고 BoxDecorration 클래스를 활용하여 아래가 둥근 형태로 만들수도 있습니다.

     

    CircleAvatar

     

    원형으로 사진을 표시하는 방법 중 가장 쉬운 방법은 CircleAvatar의 BackgroundImage 속성으로 이미지를 설정하는 것입니다. 절대 Child로 설정하면 안됩니다...

     

    currentAccountPicture: CircleAvatar(
      backgroundImage: NetworkImage('https://www.stockvault.net/data/2016/02/20/184621/preview16.jpg'),
    ),

     

    현재까지의 작업 결과는 다음과 같습니다.

     

     

Designed by Tistory.