반응형

 이번 실습은 메인 창에서 흔히 사이드 메뉴라고 하는 Sub Menu를 여는 Drawer 기능에 대해 다루어 보려고 하는데요, 영어 뜻 그대로 마치 서랍(Drawer)을 열고 닫는 기능을 통해 평소에는 메인 화면을 깔끔하게 보여주고 필요시 서브 메뉴를 열어 특정 메뉴를 선택할 수 있도록 해주는 기능입니다. 

 

 먼저 안드로이드 스튜디오를 실행하고 New Project로 아래와 같이 Empty Views Activity를 선택해 주세요.

title 제목으로 Navigation Drawer를 입력했습니다.

Drawer 기능을 이용하려면 적용하고 싶은 곳, 예를 들어 activity_main.xml에 Drawer Layout을 적용해 주면 되는데요, 
그리고 Drawer Layout은 네비게이션 아이콘을 클릭하거나 사이드를 드래그했을 때 기존 레이아웃 위에 새로운 메뉴를 보여주게 되는데, 이것이 바로 Navigation View입니다. 
따라서 Drawer 기능을 이용한다는 뜻은 Drawer Layout과 Navigation View를 세트로 같이 사용하게 되며, 아래와 같은 구조로 사용해야 하니 기억해 주세요.   왜냐하면 메인뷰 화면(View)이 먼저 존재하고 네이게이션뷰가 그 위로 오버랩 되기 때문이죠.  따라서 배치 순서를 Drawer Layout을 먼저 배치하고 그 아래에 Navigation View가 위치해야 합니다. 만약 순서가 바뀔경우 에러가 발생하게 됩니다. (아래 순서 참고)

<DrawerLayout> 
 	....
 
    <ConstraintLayout>
    	...
    </ConstraintLayout>
    
    <NavigationView>
    	...
    </NavigationView>
    
</DrawerLayout>

그럼, 

1. activity_main.xml 파일에 아래와 같이 코드를 구성해 주세요.

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    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:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Rasino IoT!"
            android:textSize="20dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/nav_menu"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"/>

</androidx.drawerlayout.widget.DrawerLayout>

여기서 위와 같이 작성하면, app:headerLayout="@layout/nav_header" 부분에 에러가 날텐데요, activity_main.xml 파일이 있는 res>>layout>> 폴더에 nav_header.xml 파일을 아래처럼 만들어주면 됩니다. 

2. nav_header.xml 파일 생성과 코드 작성

<code>

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:background="@android:color/holo_orange_dark">

</androidx.constraintlayout.widget.ConstraintLayout>

<생성결과>

 

3. nav_menu.xml 파일 생성과 코드 작성

그리고  app:menu="@menu/nav_menu"  비부분도 아래처럼 res 폴더에서 마우스 우클릭(RMB) New>>Android Resource Directory를 선택하여 menu 폴더를 만들어주고, 여기에 nav_menu.xml 파일을 생성해 주면 됩니다.

<Code>

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/item1"
        android:title="Item 1"
        android:icon="@drawable/ic_home"/>
    <item
        android:id="@+id/item2"
        android:title="Item 2"
        android:icon="@drawable/ic_home"/>
    <item
        android:id="@+id/item3"
        android:title="Item 3"
        android:icon="@drawable/ic_home"/>
</menu>

<생성 결과>

위 코드에서 Item1~3 앞에 아이콘이 나오도록 하려면 넣고 싶은 아이콘 이미지를 res>>drawable 폴더에 넣어주면 되는데요,  여기서는 간편하게 제공되는 클립아트(Clip Art) 기능인, Vector Asset에서 찾아서 넣었습니다.  그럼, 아래와 res>>drawable 폴더를 RMB 해서 Vector Asset을 클릭해 주세요. 여기서는 모두 동일한 집(Home) 아이콘을 선택했어요. 

아래와 같은 창이 뜨면, Clip art 부분을 클릭하세요.

만약, 여기서 클립아트 부분이 클릭을 해서 아래와 같은 창이 안나오거나 아무 변화가 없다면, 아래 게시글을 참고해서 특정 임시 폴더를 삭제하고 Android Studio를 재실행하면 해결될 수 있으니 참고하세요. 
(클립아트 문제 시 해결방법 : [App개발/Android_Studio] - 【AndroidStudio】 gradle 관련 에러 해결하기! )

그럼, 아래에 보이는 검색창에 home 이라고 입력해서 home 모양의 아이콘을 선택 추가해 주면 됩니다.

 

저장할 때 , 혹은 저장하고서 icon의 이름은 ic_home.xml로 너무 길지 않게 수정해 주었습니다. 

4.  MainActivity.kt 파일 생성과 코드 작성

아래와 같이 메인 액티비티 코드를 작성해 주세요. 

package com.example.navigationdrawer1

import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.example.navigationdrawer1.databinding.ActivityMainBinding
import com.google.android.material.navigation.NavigationView

class MainActivity : AppCompatActivity() {
    lateinit var toggle: ActionBarDrawerToggle
    lateinit var drawerLayout: DrawerLayout
    lateinit var navigationView: NavigationView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)
        drawerLayout = findViewById(R.id.drawerLayout)
        navigationView = findViewById(R.id.nav_view)
        toggle = ActionBarDrawerToggle(this,drawerLayout, R.string.open, R.string.close)
        drawerLayout.addDrawerListener(toggle)
        toggle.syncState()
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        navigationView.setNavigationItemSelectedListener {
            when(it.itemId) {
                R.id.item1 -> Toast.makeText(applicationContext, "Item 1 Clicked", Toast.LENGTH_SHORT).show()
                R.id.item2 -> Toast.makeText(applicationContext, "Item 2 Clicked", Toast.LENGTH_SHORT).show()
                R.id.item3 -> Toast.makeText(applicationContext, "Item 3 Clicked", Toast.LENGTH_SHORT).show()
            }
            true
        }
    }
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if(toggle.onOptionsItemSelected(item)) {
            true
        }
        return super.onOptionsItemSelected(item)
    }
}

위 코드에서 작성 중간에 toggle = ActionBarDrawerToggle(this,drawerLayout, R.string.open, R.string.close)  코드에서,

open이라는 부분과 close라는 부분에서 붉은색으로 표시가 뜰 텐데요,  그때 마우스를 Open 글자 위에 클릭 후 올려놓고 있으면 Sub메뉴가 뜨는데 "Create String Value Resource"를 클릭해서 아래처럼 각각 Open이라는 Value값을 입력해 주세요.  그리고 이어서 Close도 동일하게 진행해 주세요.

< open >

< close도 동일하게 >

그리고 내용에 보면, Drawer 메뉴가 오버랩 되며 열렸을 때 Item 1이나 Item 2, Item 3 등을 각각 선택했을 때 특정 View 페이지로 넘어가게(열게) 할 수도 있으며,  여기서는 간단히 Toast 메시지를 출력하도록 했습니다. 

navigationView.setNavigationItemSelectedListener {
    when(it.itemId) {
        R.id.item1 -> Toast.makeText(applicationContext, "Item 1 Clicked", Toast.LENGTH_SHORT).show()
        R.id.item2 -> Toast.makeText(applicationContext, "Item 2 Clicked", Toast.LENGTH_SHORT).show()
        R.id.item3 -> Toast.makeText(applicationContext, "Item 3 Clicked", Toast.LENGTH_SHORT).show()
    }
    true
}

 

이렇게 하면 기본적으로 작성해야 할 것은 모두 작성했는데요,  실행해 보면, Navigation View를 선택할 수 있는 Bar가 보이지 않는데요,  이는 안드로이드 기본 설정이 NoActionBar가 적용되어 있기 때문에 그렇습니다. 
이 때는  Action Bar가 보이도록 아래처럼   res>> values >> themes 폴더에 있는 themes.xml 파일을 수정해 주세요.  필요 시 night(다크 디스플레이 모드)화면 모드의 themes.xml 메뉴에도 적용해 주세요.

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Base.Theme.NavigationDrawer1" parent="Theme.Material3.DayNight">
        <!-- Customize your light theme here. -->
        <!-- <item name="colorPrimary">@color/my_light_primary</item> -->
    </style>

    <style name="Theme.NavigationDrawer1" parent="Base.Theme.NavigationDrawer1" />
</resources>

 

그리고 실행해 보면 아래처럼 실행 되는 것을 볼 수 있습니다.  삼선 Action Bar 부분을 터치해도 Drawer 메뉴가 열리며,  폰의 왼쪽 라인 부분을 한 손가락으로 살짝 누른 후 왼쪽에서 오른쪽으로 드래그해도 Drawer 메뉴가 열리는 것을 볼 수 있어요. (No ActionBar 사용시)


< 실행 동영상 >


감사합니다. 
오늘도 보람된 하루 되세요~

반응형