안드로이드 네비게이션 드로어(Navigation Drawer) 만들기. (How to make an Android Navigation Drawer)

2017. 10. 24. 18:03


1. 안드로이드 네비게이션 드로어 (Android Navigation Drawer)

네비게이션 드로어(Navigation Drawer)는 "항해"" 또는 "탐색"을 의미하는 Navigation이라는 단어와 "서랍"이라는 뜻을 가진 Drawer가 조합된 용어로써, 앱의 최상위 기본 탐색 메뉴로 동작하는 사용자 인터페이스 화면을 말합니다.

네비게이션 드로어(Navigation Drawer) 인터페이스


안드로이드 개발 가이드 홈페이지에서는 네비게이션 드로어의 역할에 촛점을 두어 "탐색 창"이라는 용어로 번역을 하고 있지만, 네비게이션 드로어가 동작하는 방식을 보면, 사전적 의미 그대로, "탐색 서랍"이 좀 더 직관적인 번역이 될 듯 합니다. (하지만 "탐색 서랍"은...음, 뭔가 어색하고 촌스런 이름이긴 하네요.)


네비게이션 드로어(Navigation Drawer)는 앱에서 제공하는 다양한 기능을 탐색할 수 있도록 도와주는 메인 메뉴(Main Menu)와 같은 역할을 수행합니다. 기본적으로 화면의 왼쪽 가장자리에 숨겨져 있는데, 화면 왼쪽 가장자리에서 오른쪽 방향으로 쓸어넘기는 스와이프(Swipe) 동작을 수행하거나, "액션 바(Action Bar)"의 탐색 아이콘(Navigation Icon)을 터치하여 화면에 나타나게 만들 수 있습니다.

네비게이션 드로어(Navigation Drawer) 동작


네비게이션 드로어(Navigation Drawer)가 제공하는 탐색 기능과 화면의 왼쪽 경계를 기준으로 열리고 닫히는 특수한 동작으로 인해, "네비게이션 드로어"를 마치 (NavigationDrawer라는 이름으로 만들어진) 하나의 뷰 위젯 클래스인 것으로 오해할 수 있습니다. 하지만 네이게이션 드로어(Navigation Drawer)는 하나의 뷰 위젯 클래스가 아니라, 머티리얼 디자인의 "디자인 패턴" 중 하나입니다. (네비게이션 드로어 디자인 패턴에 대한 내용은 "https://material.io/guidelines/patterns/navigation-drawer.html" 에서 확인할 수 있습니다.)


네비게이션 드로어(Navigation Drawer)가 단순히 뷰 위젯으로 존재하지 않는다면, 어떤 방법으로 만들 수 있는 것일까요? 정답은 바로, 화면의 가장자리에서 뷰(View)가 열리고 닫히는 기능을 만들 때 사용하는 레이아웃인 드로어레이아웃(DrawerLayout)을 사용하는 것입니다.

1.1 네비게이션 드로어(Navigation Drawer)와 드로어레이아웃(DrawerLayout)

[안드로이드 드로어레이아웃]에서 설명했듯이, 드로어레이아웃(DrawerLayout)은 자신의 영역 안에서 자식 뷰(View)가 "Drawer(서랍)"와 같은 동작을 수행하도록 만들어주는 레이아웃입니다. 앞서 설명한 네비게이션 드로어(Navigation Drawer)의 동작 방식과 정확히 일치하죠. 그러므로 네이베이션 드로어(Navigation Drawer)를 만들 때는 DrawerLayout을 액티비티의 루트 레이아웃으로 사용합니다.


그리고 DrawerLayout의 Drawer에는 탐색 항목이 나열됩니다. 탐색 항목을 표시할 뷰는 앱의 컨텐츠에 따라 다양한 구성이 가능하지만, 일반적으로 리스트뷰(ListView) 또는 리사이클러뷰(RecyclerView)를 사용합니다.


또한 DrawerLayout의 주 화면으로는 FrameLayout을 주로 사용하는데, 이는 FrameLayout이 액자(Frame)처럼 화면에 표시될 뷰(View)를 바꿔가면서 표시하기가 용이하기 때문입니다. 특히, FrameLayout이 프래그먼트(Fragment)의 컨테이너 역할을 수행하므로, Drawer의 탐색 항목 선택 시 주 화면에 표시될 내용을, 프래그먼트를 사용하여 변경하기가 쉽다는 장점이 있죠.

네비게이션 드로어(Navigation Drawer) 기본 레이아웃


2. 네비게이션 드로어(Navigation Drawer) 만들기.

자, 그럼 이제, 예제를 통해 네비게이션 드로어(Navigation Drawer)를 만드는 방법에 대해 알아보겠습니다. 예제는 아래와 같은 레이아웃으로 구성됩니다.

DrawerLayout 예제 레이아웃


네비게이션 드로어(Navigation Drawer)에 대한 쉬운 이해를 위해, 예제에서는 DrawerLayout의 주 화면으로 텍스트뷰(TextView)를 사용합니다.

2.1 MainActivity의 레이아웃 작성하기.

가장 먼저, MainActivity의 레이아웃 리소스 XML을 작성합니다. (참고로, 본문의 프로젝트는 안드로이드 스튜디오에서 프로젝트 생성 시, 액티비티 선택 단계에서 "Basic Activity"를 선택하였습니다.)

[STEP-1] "content_main.xml" - MainActivity 레이아웃 리소스 XML 파일
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.recipes4dev.examples.navigationdrawerexample.MainActivity"
    tools:showIn="@layout/activity_main">

    <android.support.v4.widget.DrawerLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:id="@+id/drawer">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textSize="48sp"
            android:text="CONTENTS"
            android:background="#FFFFFF"
            android:textColor="#000000"
            android:id="@+id/drawer_content"/>

        <ListView
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:background="#FFC107"
            android:id="@+id/drawer_menulist" />

    </android.support.v4.widget.DrawerLayout>

</android.support.constraint.ConstraintLayout>

레이아웃 소스 코드에서 가장 먼저 눈여겨 봐야할 부분은 DrawerLayout에 추가되는 자식(Children)들의 순서입니다. 기본적으로, 주 화면으로 표시될 뷰를 첫 번째 자식(Child)으로 선언하고, Drawer로 사용될 뷰를 마지막 자식(Child)으로 선언합니다. 예제에서는 ListView가 Drawer로 사용될 것이므로, 레이아웃의 가장 마지막에 추가하였습니다.


그 다음, Drawer로 사용되는 ListView에 대해 layout_gravity 속성을 사용하여 Drawer가 어느 방향에서 나타날 것인지를 결정해야 합니다. left(start) 또는 right(end) 값을 지정할 수 있으며, 네비게이션 드로어 패턴에서는 기본적으로 left(start)를 사용합니다.


마지막으로 Drawer의 layout_width와 layout_height를 적절한 값으로 지정해야 합니다. 보통 layout_width는 부모인 DrawerLayout의 너비보다 작은 상수 값을 사용하며, layout_height는 부모의 높이에 딱 맞게 match_parent 값을 지정합니다.


각 항목에 대한 좀 더 자세한 설명은 [안드로이드 드로어레이아웃]의 내용을 참고하시기 바랍니다.

2.2 Drawer의 리스트뷰 초기화.

다음 단계는 Drawer에 표시될 리스트뷰를 초기화하는 것입니다.

[STEP-2] "MainActivity.java" - onCreate() 함수에서 리스트뷰 초기화.
public class MainActivity extends AppCompatActivity {

    ListView listview = null ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // ... 코드 계속

        final String[] items = {"WHITE", "RED", "GREEN", "BLUE", "BLACK"} ;
        ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, items) ;

        listview = (ListView) findViewById(R.id.drawer_menulist) ;
        listview.setAdapter(adapter) ;

        // 코드 계속 ...
    }
}

2.3 리스트뷰 아이템 클릭 이벤트 처리

이제 Drawer에 표시된 리스트뷰의 아이템을 선택하면, 주 화면의 컨텐츠를 변경하는 코드를 작성합니다. 예제에서는 컨텐츠로 하나의 텍스트뷰만을 사용하며, 아이템 선택 시 텍스트뷰의 텍스트, 배경색, 글자색을 변경하도록 만듭니다.

[STEP-3] "MainActivity.java" - 리스트뷰 아이템 클릭 이벤트 처리.
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        // ... 코드 계속

        listview.setOnItemClickListener(new ListView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View v, int position, long id) {

                TextView contentTextview = (TextView) findViewById(R.id.drawer_content) ;

                switch (position) {
                    case 0 : // WHITE
                        contentTextview.setBackgroundColor(Color.rgb(0xFF, 0xFF, 0xFF)) ;
                        contentTextview.setTextColor(Color.rgb(0x00, 0x00, 0x00)) ;
                        contentTextview.setText("WHITE") ;
                        break ;
                    case 1 : // RED
                        contentTextview.setBackgroundColor(Color.rgb(0xFF, 0x00, 0x00)) ;
                        contentTextview.setTextColor(Color.rgb(0xFF, 0xFF, 0xFF)) ;
                        contentTextview.setText("RED") ;
                        break ;
                    case 2 : // GREEN
                        contentTextview.setBackgroundColor(Color.rgb(0x00, 0xFF, 0x00)) ;
                        contentTextview.setTextColor(Color.rgb(0x00, 0x00, 0x00)) ;
                        contentTextview.setText("GREEN") ;
                        break ;
                    case 3 : // BLUE
                        contentTextview.setBackgroundColor(Color.rgb(0x00, 0x00, 0xFF)) ;
                        contentTextview.setTextColor(Color.rgb(0xFF, 0xFF, 0xFF)) ;
                        contentTextview.setText("BLUE") ;
                        break ;
                    case 4 : // BLACK
                        contentTextview.setBackgroundColor(Color.rgb(0x00, 0x00, 0x00)) ;
                        contentTextview.setTextColor(Color.rgb(0xFF, 0xFF, 0xFF)) ;
                        contentTextview.setText("BLACK") ;
                        break ;
                }

                // 코드 계속 ...
            }
        });
    }
}

2.4 리스트뷰의 아이템을 선택하면 Drawer 닫기.

마지막으로, Drawer의 리스트뷰에서 아이템을 선택하고 나면, Drawer가 닫히도록 만듭니다. 열려 있는 Drawer를 닫기 위해서는 DrawerLayout의 closeDrawer() 함수를 호출하면 됩니다.

[STEP-4] "MainActivity.java" - DrawerLayout의 Drawer 닫기.

public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { // ... 코드 계속 listview.setOnItemClickListener(new ListView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View v, int position, long id) { // ... 코드 계속 // close drawer. DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer) ; drawer.closeDrawer(Gravity.LEFT) ; } }); } }

3. 예제 실행

예제 코드를 작성하고 실행하면, 아래 그림과 같은 화면이 표시됩니다.

네비게이션 드로어(Navigation Drawer) 예제 실행 화면


실행된 초기 화면만 보면 아무런 기능이 없는 것처럼 보이지만, 화면 왼쪽 가장자리를 스와이프하면 리스트뷰가 표시된 Drawer가 나타나는 것을 확인할 수 있습니다. 그리고 리스트뷰의 아이템을 선택하면, 선택된 아이템에 따라 주 화면의 색상과 텍스트가 변경되는 것을 확인할 수 있습니다.

4. 참고

.END.


ANDROID 프로그래밍/NAVIGATION