Android Studio - DrawerLayout

지훈·2021년 12월 30일
0

DrawerLayout

Drawer : 서랍
DrawerLayout은 서랍이 열리고 닫히는 것처럼 평소에는 화면 한쪽에 숨겨져 있다가 사용자가 액션을 취하면 화면에 나타나는 기능을 만들 수 있게 해주는 레이아웃.

하지만 Layout 자체가 화면에서 나타나거나 사라지는 동작을 수행하는 것은 아니다! DrawerLayout에 추가된 자식이 Layout 안에서 서랍과 같은 동작을 수행하는 것.
자식들 중 layout_gravity 속성값을 가지지 않은 자식들은 기본적으로 표시되는 주화면, layout_gravity 속성값을 가진 자식만 Drawer로서 동작 지정된 left or right로 열림.

  • DrawerLayout은 Drawer Navigation라고도 한다.
  • 창의 각 세로 모서리에 대해 하나의 drawer View만 가질 수 있다. 만약 창의 세로 모서리당 두개 이상의 Drawer View를 구성하면 런타임에 예외가 던져진다.
  • Primary 콘텐츠 뷰를 첫번째 자식을 너비와 높이를 layout_gravity없이 match parent로 설정하고 다음 자식을 layout_gravity를 사용해 Drawer로 설정한다.
  • 안드로이드 디자인 가이드에 따르면 왼쪽 Drawer는 응용 프로그램 탐색 콘텐츠, 오른쪽 Drawer는 현재 콘텐츠에 대한 작업으로 만든다.

기본 레이아웃 구성

기본적으로 두개의 자식이 필요하다. 하나는 Drawer가 표시되지 않은 상태인 주 화면, 다른 하나는 Drawer 역할을 수행할 화면

layout_gravity = "left" 혹은layout_gravity = "start" => 왼쪽에서 열리는 Drawer
layout_gravity = "right" 혹은layout_gravity = "end" => 오른쪽에서 열리는 Drawer
Drawer가 왼쪽과 오른쪽에서 하나씩 열리도록 지정할 수 있지만 한 방향에서 두개의 Drawer를 열리게 할 수는 없다.

Drawer는 너비는 DrawerLayout보다 작은 고정값, 높이는 DrawerLyaout의 높이와 같은 match parent로 지정하는 것이 일반적이다. 물론 Drawer가 아닌 주화면은 DrawerLayout의 전체 영역에 표시되므로 주화면인 DrawerLayout의 첫번째 자식은 너비와 높이가 match parent이다.

기본 동작

  • Drawer를 열 때 Drawer가 있는 Edge를 Swipe
  • 닫을 때는 Drawer Swipe하거나 Drawer가 아닌 영역을 터치하여 닫는다.
  • 물론 Swipe가 아닌 특정 버튼 클릭 등을 통해 Drawer가 표시되도록 만들 수 있다. (DrawerLayout에서 제공하는 함수 사용)

Drawer 열고 닫기 코드

DrawerLayout에서 제공되는 함수를 호출하면 외부 버튼 또는 메뉴를 통해 열리거나 닫히게 할 수 있다.

  • openDrawer 종류

    • openDrawer(View drawerView, boolean animate)
      애니매이션과 함께 drawerView 열기
    • openDrawer(View drawerView)
      drawerView열기 animate에 따라 애니매이션 결정
    • openDrawer(int gravity)
      지정된 Drawer를 gravity 방향에서 애니매이션과 함께 열기
    • openDrawer(int gravity, boolean animate)
      지정된 Drawer를 gravity 방향에서 열기 animate에 따라 애니매이션 결정
  • closeDrawer 종류

    • closeDrawer(View drawerView)
      애니매이션과 함께 drawerView 닫기
    • closerDrawer(int gravity)
      gravity 방향에 있는 Drawer를 애니매이션과 함께 닫기
    • closeDrawer(View drawerView, boolean animate)
      drawerView를 애니매이션과 함께 닫기
    • closeDrawer(int gravity, boolean animate)
      지정된 Drawer를 gravity 방향으로 열기. animate에 따라 애니메이션 여부 결정
    • closeDrawers()
      현재 열려 있는 모든 Drawer를 애니메이션과 함께 닫기.

    Drawer 잠그기

Drawer를 열린 상태 혹은 닫힌 상태로 고정시키는 것.
DrawerLayout의 setDrawerLockMode() 함수를 통해 Drawer 잠그기 기능을 활성화|비활성화

  • LOCK_MODE_UNLOCKED : 잠그기 기능 비활성화.
  • LOCK_MODE_CLOSED : Drawer가 닫힌채로 잠그기. 만약 열려있는 상태였다면 닫히고 잠김
  • LOCK_MODE_OPEND : Drawer가 열린채로 잠그기. 만약 닫혀있는 상태였다면 열리고 잠김

잠겨있는 상태에서 Swipe로 열고 닫을 수 없지만 함수 openDrawer()나 closeDrawer로는 열고 닫을 수 있다.

DrawerLayout 사용하기

사용하 레이아웃은 아래와 같은 구성

버튼 클릭 이벤트 처리

  • open 이벤트
        val buttonOpen = findViewById<Button>(R.id.open)
        buttonOpen.setOnClickListener {
            val drawer = findViewById<DrawerLayout>(R.id.drawer)
            if (!drawer.isDrawerOpen(Gravity.LEFT)) {
                drawer.openDrawer(Gravity.LEFT)
            }
        }
  • close 이벤트
        val buttonClose = findViewById<Button>(R.id.close)
        buttonClose.setOnClickListener {
            val drawer = findViewById<DrawerLayout>(R.id.drawer)
            if (drawer.isDrawerOpen(Gravity.LEFT)) {
                drawer.closeDrawer(Gravity.LEFT)
            }
        }
  • Lock 이벤트 처리
        val checkboxLock = findViewById<CheckBox>(R.id.lock)
        checkboxLock.setOnClickListener {
            val drawer = findViewById<DrawerLayout>(R.id.drawer)
            if (checkboxLock.isChecked()) {
                if (drawer.isDrawerOpen(Gravity.LEFT)) {
                    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN)
                } else {
                    drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                }
            } else {
                drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
            }
        }

DrawerLayout 주의사항

Drawer로 동작하는 자식은 left(start) 또는 right(end)만 가능

왼쪽 Edge와 오른쪽 Edge에 Drawer로 동작하는 자식을 만들 수 있다. 단, 왼쪽 Edge나 오른쪽 Edge에 두개 이상의 Drawer를 만들 수 없다.

Drawer가 없는 방향에 코드로 연다면 에러

만약 오른쪽 Edge에는 Drawer가 없다고 하자. 이 때 drawer.openDrawer(Gravity.RIGHT)로 Drawer를 열려고 시도한다면 에러가 발생한다.

추가사항

  • Drawer가 화면에 보이는 상황에서 단말기의 뒤로가기 버튼을 눌렀을 때의 반응 등의 이벤트를 함수를 이용해 추가할 수 있다.

  • 안드로이드 디자인 가이드에 따르면 Drawer는 보통 Header와 Content 영역으로 나뉜다. Content 영역에 아이콘을 눌러 다른 Activity나 Fragment로 이동하도록 디자인할 수 있을 것이다.

출처 :
https://recipes4dev.tistory.com/139
https://soohyun6879.tistory.com/77
https://duzi077.tistory.com/167
https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout

profile
안드로이드 개발 공부

0개의 댓글