Android/Kotlin
[Android, Kotlin] Navigation View
겨울시인
2022. 4. 20. 00:07
1. 기능 구현
- Main 화면에서 메뉴 Image 를 클릭시 Item 메뉴 활성화
- 활성화된 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 속성
- single : 그룹의 한 항목만 선택 (like. 라디오버튼)
- all : 모든 항목을 선택 가능 (like. 체크박스)
- 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
- 최상단의 기본 Layout을 변경(ConstraintLayout -> DrawerLayout)
- 최상단 DrawerLayout 내부에 ConstraintLayout을 만들어 보자.
- ConstraintLayout 내부에 Navigation Menu를 불러올 버튼을 ImageView로 만들어 보자.
- 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 메뉴 활성화 상태