Android/Kotlin

[Android, Kotlin] Navigation View

겨울시인 2022. 4. 20. 00:07

1. 기능 구현

  1. Main 화면에서 메뉴 Image 를 클릭시 Item 메뉴 활성화
  2. 활성화된 Item 메뉴에서 Item 클릭시 해당 Item 에 대한 Toast 메세지 후, Item 메뉴 비활성화

 
 

2. Android Studio에서 기본 프로젝트(with empty activity) 생성하자!

생성시 'Empty Activity'로 기본 생성

 
 

3. ViewBinding 사용을 위한 build.gradle 설정

  android {
          // 뷰 바인딩 옵션 활성화
          viewBinding {
              enabled = true
          }
      }

 
 

4. Navigation View 사용하기 위한 build.gradle 에 implementation 추가 -> Sync Now

 
 

5. 리소스폴더(res)에 Navigation 전용 Menu 폴더 생성

res -> New -> Android Resource Directory

Resource Type = menu 선택 -> OK

 
 

6. 프로젝트에 쓰일 아이콘(icon)들을 추가해 보자. (Android Studio 에서 기본 제공)

res -> drawable -> New -> Vector Asset : Configure Vector Asset

Clip Art -> 기본 제공되는 여러 Image 중, 원하는 이미지들을 추가해보자.

 
 

7. navi_menu.xml

res -> menu -> New -> Menu Resource File : navi_menu.xml 생성

  • menu : 메뉴 항목의 컨테이너인 Menu를 정의. 파일의 루트 노드여야 하고 하나 이상의 item과 group 요소를 가질 수 있다.
  • group : item 요소를 위한 투명 컨테이너입니다(선택사항). 이 컨테이너를 사용하면 메뉴 항목을 분류하여 활성 상태와 가시성 등의 속성을 공유할 수 있다.
  • item : 메뉴 내 단일 항목을 나타내는 MenuItem을 생성합니다. 하위 메뉴를 생성하기 위한 중첩 menu 요소를 포함할 수 있다.
  • android:checkableBehavior 속성
    1. single : 그룹의 한 항목만 선택 (like. 라디오버튼)
    2. all : 모든 항목을 선택 가능 (like. 체크박스)
    3. none : 항목 선택 불가
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">

        <item android:id="@+id/access"
            android:icon="@drawable/ic_baseline_accessibility_24"
            android:title="접근성"/>
        <item android:id="@+id/email"
            android:icon="@drawable/ic_baseline_email_24"
            android:title="이메일"/>
        <item android:id="@+id/message"
            android:icon="@drawable/ic_baseline_send_24"
            android:title="메시지"/>

    </group>
</menu>

 
 

8. activity_main.xml

  1. 최상단의 기본 Layout을 변경(ConstraintLayout -> DrawerLayout)
  2. 최상단 DrawerLayout 내부에 ConstraintLayout을 만들어 보자.
  3. ConstraintLayout 내부에 Navigation Menu를 불러올 버튼을 ImageView로 만들어 보자.
  4. NavigationView 를 만들어 보자. (ConstraintLayout 과 DrawerLayout 사이)
<?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/layout_drawer"
    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="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/btn_navi"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_baseline_menu_64" />
    </androidx.constraintlayout.widget.ConstraintLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/naviView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/navi_menu"
        />


</androidx.drawerlayout.widget.DrawerLayout>

 
 

9. MainActivity.kt

  • 추가로 Interface NavigationView.OnNavigationItemSelectedListener 를 상속받자.
  • Interface 상속에 따른 구현 메소드 onNavigationItemSelected 를 override 하자.
    • 메소드 내부 구현 : Toast 메세지로 선택된 Item 을 알려주도록 하자.
  • onCreate 구현
    • ImageView 에 setOnClickListener 설정 (openDrawer)
    • setNavigationItemSelectedListener : 메뉴의 아이템들에게 클릭 속성을 부여
  • onBackPressed 구현
    • 메뉴가 활성화 된 상태에서 back 했을때 앱이 종료되는 문제를 해결하기 위해 구현
      • 메뉴가 활성화된 상태에서 back -> 메뉴 비활성화
      • 메뉴가 비활성화된 상태에서 back -> 앱 종료
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private var mBinding:ActivityMainBinding? = null
    private val binding get() = mBinding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //setContentView(R.layout.activity_main)

        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.btnNavi.setOnClickListener{
            // START = left,  END = right
            binding.layoutDrawer.openDrawer(GravityCompat.START)
        }
        // 네비게이션 메뉴의 아이템들에게 클릭 속성을 부여.
        binding.naviView.setNavigationItemSelectedListener(this)

    }

    // 네비게이션 아이템 클릭시 수행하는 구문
    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        when(item.itemId)
        {
            R.id.access -> Toast.makeText(applicationContext, "접근성", Toast.LENGTH_SHORT).show()
            R.id.email -> Toast.makeText(applicationContext, "이메일", Toast.LENGTH_SHORT).show()
            R.id.message -> Toast.makeText(applicationContext, "메시지", Toast.LENGTH_SHORT).show()
        }
        // 펼쳐저있는 네비게이션 뷰 닫기
        binding.layoutDrawer.closeDrawers()
        return false
    }

    override fun onBackPressed() {
        if(binding.layoutDrawer.isDrawerOpen(GravityCompat.START))
        {
            binding.layoutDrawer.closeDrawers()
        }
        else {
            // 일반 Back 버튼 실행 (finish() 같은 역할을 함)
            super.onBackPressed()
        }
    }
}

 
 

10. 실행결과

Item 메뉴 비활성화 상태

Item 메뉴 활성화 상태

 
 

11. Reference

유튜버 홍드로이드님의 안드로이드 코틀린 앱 만들기 #6