Development

네비게이션 드로어(Navigation Drawer) 사용하기

네비게이션 드로어(Navigation Drawer) 예시

예전에 슬라이딩 메뉴 라이브러리를 추천하는 글을 쓴 적이 있다. 이 글을 쓴지 벌써 거의 3년이 다 되어간다. 그 3년 동안 안드로이드 개발에는 많은 변화가 있어왔다. 안드로이드도 버전업이 많이 되었고, 구글은 안드로이드 앱들의 디자인을 자사의 마테리얼(Material) 디자인으로 통일하기 위한 궁리를 많이 해왔다.

슬라이딩 메뉴는 네비게이션 드로어(Navigation Drawer)라는 이름으로 구글의 마테리얼 디자인 가이드에 포함되었으며, 이를 구현하기 위해서 또 많은 이들이 라이브러리를 만들어 공개해왔다. 그러나 그 노력들이 무색하게도, 구글은 서포트 라이브러리(Support Library)에 네비게이션 드로어를 포함시켰다. 덕분에 그 후로 오픈소스 라이브러리들은 서포트 라이브러리를 참조하여 사용하기 편리하도록 코드를 바꿔주는 역할만 하는 방향으로 개발해나가기 시작했다.

하지만 개인적으로는 왠만하면 개발사에서 제공하는 방법을 직접 사용하는걸 추천하고 싶다. 추가적인 라이브러리를 설치해야 하는 부담감도 있고, 직접 다루는 편이 성능 최적화나 커스터마이징을 하기에 좀더 편리하기 때문이다.

본인의 앱 Seeko Mobile에는  이미 구글의 서포트 라이브러리만을 이용하여 네비게이션 드로어를 구현해 놨는데, 아직도 상당수의 앱에는 네비게이션 드로어가 제대로 구현되어 있지 않다. 아직까지도 예전에 내가 작성한 슬라이딩 메뉴 라이브러리 추천글을 찾는 사람들이 많은데, 새로운 “정석적인” 방법을 다들 사용했으면 하는 바람에 이렇게 글을 쓴다.

이하의 글은 구글의 레퍼런스 문서 Creating a Navigation Drawer를 번역한 것이다. 개발자들에게 도움이 되었으면 좋겠다. 일부는 이해를 위해 의역하거나 변경한 부분도 있다.


네비게이션 드로어는 화면 왼쪽에 앱의 주요 운용 선택지(navigation options)를 표시하기 위한 패널이다. 네비게이션 드로어는 일반적으로 숨겨져 있지만, 스크린의 왼쪽 모퉁이에서부터 화면 가운데로 손가락을 밀거나(swipe), 앱의 최상위 화면에서 액션바에 있는 앱 아이콘을 터치할 시에 나타난다.

이 강좌는 서포트 라이브러리에서 제공되는 DrawerLayout API를 사용하여 어떻게 네비게이션 드로어를 사용할 것인지를 보여주고자 한다.

네비게이션 드로어 디자인

네비게이션 드로어를 앱에 적용하기 전에, 네비게이션 드로어 디자인 가이드에서 정의된 용례와 디자인 원리에 대해서 이해해야 한다.

드로어 레이아웃(Drawer Layout) 작성하기

네비게이션 드로어를 추가하려면, DrawerLayout 객체를 레이아웃 최상위 뷰(view)로써 가지는 유저 인터페이스를 선언해야 한다. DrawerLayout 안에는 각각 화면의 주요 내용을 담을 뷰(드로어가 숨겨져 있을때 보여질 내용)와 네비게이션 드로어가 될 뷰를 추가한다.

다음의 코드는 두개의 자식 뷰를 가지고 있는 DrawerLayout을 사용하는 예제이다. FrameLayout이 주요 내용을 담고 있고(런타임때에 Fragment를 가져온다), ListView가 네비게이션 드로어로써 작동한다.

이 예제 레이아웃은 중요한 특성 몇가지를 보여준다.

  • 주요 컨텐츠 뷰(FrameLayout)는 DrawerLayout의 첫번째 자식뷰가 되어야 한다. XML의 순서는 Z축 순서를 나타내며, 드로어는 항상 최상단에 있어야 하기 때문에다. (뒤에 있을수록 나중에 그려지므로 맨 위에 나타나게 된다는 의미)
  • 주요 컨텐츠 뷰는 부모 뷰의 너비와 높이에 맞춰져야 한다. 왜냐면 네비게이션 드로어가 보이지 않을 때 전체 UI를 보여주는 뷰이기 때문이다.
  • 드로어 뷰(ListView)는 android:layout_gravity 속성값이 반드시 정해져야 한다. RTL(Right-To-Left) 언어를 지원하기 위해서는, 해당 속성값을 "left"대신 "start"로 설정해야 한다. (그렇게 해야 드로어는 RTL 언어에 대응하여 오른쪽에서 나타나게 된다.)
  • 드로어 뷰는 폭의 크기를 dp 단위로 설정해야 하며, 높이는 부모 뷰에 맞춰야 한다. 드로어 폭은 사용자가 주요 컨텐츠의 일부분을 항상 볼 수 있도록 320dp를 넘어서는 안된다.

드로어 리스트 초기화하기

Activity에서 가장 먼저 해야하는 것 중 하나는 네비게이션 드로어의 아이템 리스트를 초기화 하는 것이다. 네가 어떻게 초기화 할 것인가는 앱의 컨텐츠에 달려있지만, 네비게이션 드로어는 보통 ListView를 포함하고 있으므로, 목록은 Adapter(예를 들어 ArrayAdapterSimpleCursorAdapter)를 이용해 초기화되어야 한다.

다음은 문자열 배열을 표시하는 네비게이션 리스트를 초기화 하는 방법에 대한 예시이다.

이 코드는 또한 setOnItemClickListener()를 호출하여 네비게이션 드로어에 대한 클릭 이벤트를 받을 수 있게 하고 있다. 다음 차례로, 이 인터페이스를 상속하여 사용자가 목록 아이템을 선택했을 때 컨텐츠 뷰를 변경하는 방법에 대해서 보여주고자 한다.

네비게이션 클릭 이벤트를 다루기

사용자가 드로어 목록의 아이템을 선택했을 때, 안드로이드 시스템은 setOnItemClickListener()에 의해 주어진 OnItemClickListener 객체의 onItemClick() 함수를 호출한다.

onItemClick() 함수에서 무엇을 해야하는가는 앱의 구조가 어떻게 만들어져 있는가에 따라 달라진다. 다음의 예제는 네비게이션 아이템을 선택했을 때, 주요 컨텐츠 뷰에 클릭한 아이템에 따라 다른 Fragment를 삽입하는 것을 보여주고 있다. (FrameLayoutR.id.content_frame의 아이디값으로 설정되어 있다.)

열기/닫기 이벤트 감지하기

드로어가 열리고 닫힐 때 발생하는 이벤트를 감지하기 위해, DrawerLayoutsetDrawerListener()를 호출하여, DrawerLayout.DrawerListener를 상속한 객체를 변수로 넘겨주어야 한다. 이 인터페이스는 onDrawerOpened()onDrawerClosed()와 같은 드로어 이벤트에 대한 콜백 함수를 제공하고 있다.

그러나, 만약에 액션 바를 사용하고 있다면, DrawerLayout.DrawerListener를 상속하는 것 대신, ActionBarDrawerToggle 클래스를 확장하여 사용하는 것이 좋다. ActionBarDrawerToggle 클래스는 DrawerLayout.DrawerListener를 상속하고 있으므로, 앞서 말한 콜백함수들을 여전히 오버라이드하여 사용할 수 있다. 또한, 해당 클래스는 액션 바 아이콘과 네비게이션 드로어 사이의 적절한 상호작용을 가능하게 한다. (이는 다음 차례에서 다룰 것이다.)

네비게이션 드로어 디자인 가이드에 따라, 드로어가 보여질때 액션바의 내용을 수정해야만 한다. 메인 컨텐츠와 관련된(contextual to the main content) 타이틀과 액션 아이템을 변경하는 등의 작업이 이뤄져야 한다. 다음의 코드는 ActionBarDrawerTaggle 클래스의 인스턴스에 있는 DrawerLayout.DrawerListener 콜백 함수들을 오버라이드하여 액션바의 내용을 수정하는 방법에 대한 예제이다.

다음 차례에서는 ActionBarDrawerToggle의 생성자 매개변수들과 액션 바 아이콘과의 상호작용을 통제하기 위해 추가로 필요로 되는 절차들에 대해서 설명할 것이다.

앱 아이콘을 눌러 드로어 열고 닫기

사용자들은 왼쪽/오른쪽으로 화면을 미는(swipe) 제스쳐를 통해 네비게이션 드로어를 열고 닫을 수 있다. 하지만 액션바를 사용한다면, 사용자들이 앱 아이콘의 터치만으로도 드로어를 열고 닫을 수 있도록 해야 한다. 앱 아이콘은 또한 네비게이션 드로어의 개폐 여부를 특별한 아이콘으로 표시할 수 있다. 이러한 모든 작업은 이전 차례에서의 ActionBarDrawerToggle 클래스를 상속하여 구현할 수 있다.

ActionBarDrawerToggle이 작동하도록 하기 위해서는, 해당 클래스의 생성자를 통해 인스턴스를 생성해야 하며, 이는 다음의 매개변수들을 필요로 한다.

  • 드로어를 포함한 Activity
  • DrawerLayout
  • 드로어 상태표시자로 사용될 이미지 리소스(Drawable resource)
    표준 네비게이션 드로어 아이콘은 Download the Action Bar Icon Pack에서 다운로드 받을 수 있다.
  • (접근성을 위하여) “드로어를 여는” 행위를 나타낼 문자열 리소스
  • (접근성을 위하여) “드로어를 닫는” 행위를 나타낼 문자열 리소스

ActionBarDrawerToggle의 하위 클래스를 드로어행위 감지자(drawer listener)로 생성했는지와는 무관하게, Activity 생성주기(lifecycle) 전체에 걸쳐 몇 군대에서 ActionBarDrawerToggle을 호출할 필요가 있다.

네비게이션 드로어의 완성된 예시는 샘플을 다운로드하여 확인할 수 있다.

Published by AlphaFactory

프로그래밍을 좋아하는 건축공학도입니다. 블로그는 프로그래밍과 IT쪽으로 현재 운영중이지만 앞으로 건축관련 내용도 다뤄보려고 합니다. 원래 Android 및 Java를 주력으로 다뤘지만 최근에는 개인 프로젝트로 인하여 C#을 주력으로 다루고 있습니다.

4 thoughts on “네비게이션 드로어(Navigation Drawer) 사용하기”

  1. Dreaming Tiny Poro says:

    상당히 어렵긴 합니다만, 덕분에 큰 도움이 되었습니다. 감사합니다.

    1. AlphaFactory says:

      도움이 되었다니 감사합니다. 😀

  2. 김병희 says:

    수많은 글들 중 눈에 띄는 멋진 글입니다.
    – 열기/닫기 이벤트 감지하기
    – 앱 아이콘을 눌러 드로어 열고 닫기
    다 읽어보기 전이지만, 위 두 제목만으로도 이 글 발견한 것이 행운으로 느껴집니다.

    질문 하나 드려도 될까요?

    DrawerLayout에는 layout_margin 속성이 공개되지 않은 모양인데, 마진을 다룰 수 있는 방법이 있을까요?
    목적은 DrawerLayout을 끌어내기 전에도 DrawerLayout의 가장자리가 약간 보이게 하는 것입니다.
    방법이 있으면 가르쳐 주시기 바랍니다.

    감사합니다.

    1. AlphaFactory says:

      DrawerLayout을 상속하여 직접 구현하시는 것 말고는 따로 방법이 없을것으로 보입니다.

댓글은 블로그 운영에 힘이 됩니다!