Android/DrawerLayout

[Android] DrawerLayout으로 Side Navigation 구현하기

O_Gyong 2022. 12. 15.

DrawerLayout은 자식 레이아웃 중 하나를 펼치고 접는 기능을 하게 해주는 레이아웃이다.

 

자식 레이아웃 중 하나에 layout_gravity 속성을 start(left)나 end(right)를 부여하는 것으로 DrawerLayout을 쓸 수 있다.

단, layout_gravity 속성을 가진 자식 레이아웃은 하나여야 하고 layout_height은 match_parent가 되어야 한다.

(그렇지 않으면 런타임 에러가 발생한다.)

 

drawer로 사용하기 위해 layout_gravity 속성을 지닌 자식 레이아웃 이외에 여러 개를 선언해 봤는데

화면에는 마지막에 작성된 레이아웃만 보였다.

DrawerLayout을 사용할 때 drawer로 표시할 레이아웃 하나와 메인 콘텐츠를 보여줄 레이아웃까지 해서

자식 레이아웃은 두 개만 생성하는 게 좋아 보인다.


DrawerLayout 예제

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dl_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#2E8BD5" />

    <include
        android:id="@+id/in_view_drawer"
        layout="@layout/view_drawer"/>

</androidx.drawerlayout.widget.DrawerLayout>

drawer로 사용할 레이아웃은 xml을 따로 만들고 include 태그를 사용했다.

(include를 사용하지 않아도 상관없다.)

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer"
    android:layout_width="310dp"
    android:layout_height="match_parent"
    android:background="@color/purple_200"
    android:layout_gravity="start"
    android:paddingStart="20dp"
    android:orientation="vertical">

view_drawer.xml의 시작 부분이다.

layout_gravity="start"로 drawer의 동작 방식을 선언하고 있다.

start로 선언하게 되면 레이아웃이 왼쪽에서 열린다.

(반대로 end를 하면 오른쪽에서 열린다.)

(왼쪽) start, (오른쪽) end


xml에서 DrawerLayout만 선언하고 코드 상으로 아무 작업을 하지 않았는데 스와이프로 화면을 펼치고 닫을 수 있다.

 

스와이프를 막거나 버튼을 눌렀을 때 drawer를 펼치고 접으려면 코드 상으로 처리를 해야 한다.

drawer의 스와이프 동작을 막고 열기 버튼과 닫기 버튼을 이용해 drawer를 열거나 닫으려 한다.

        // drawer 잠금
        mBinding.dlMain.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)

        // 열기 버튼
        mBinding.btnMain.setOnClickListener {
            mBinding.dlMain.open()
//            mBinding.dlMain.openDrawer(GravityCompat.START)
//            mBinding.dlMain.openDrawer(Gravity.LEFT)
        }

        // 닫기 버튼
        mBinding.inViewDrawer.ivDrawerClose.setOnClickListener {
            mBinding.dlMain.close()
//            mBinding.dlMain.closeDrawer(GravityCompat.START)
//            mBinding.dlMain.closeDrawer(Gravity.LEFT)
        }

setDrawerLockMode는 상수 값을 받아 drawer의 동작을 제어할 수 있다.

그중에서 LOCK_MODE_LOCKED_CLOSED는 drawer를 잠금 상태로 변경하지만 코드로 접근할 수 있게 한다.

해당 값을 전달하여 스와이프 동작이 안되도록 했다.

 

drawer를 열거나 닫게 하려면 open, openDrawer / close, closeDrawer 메서드를 사용하면 된다.

주의할 점은 drawer layout의 layout_gravity가 end(right)로 되어있을 경우 open(close)를 사용하게 되면 앱이 죽는다.

open(close)의 경우 start인 경우에 동작하기 때문에 end의 경우 openDrawer(closeDrawer)를 사용해야 한다.

참고 자료

전체 코드

댓글