본문 바로가기
Android

[Android] BottomNavigationView(하단 네비게이션) 구현하기

by JongSeok 2023. 1. 6.

최근 출시되는 대부분의 앱에서 다음과 같은 하단 바 형태의 메뉴를 보신 적이 있을 겁니다.

'커리어리'의 하단 바

이런 하단 바 형태의 디자인을 안드로이드에서는 'BottomNavigationView' 라고 합니다.

BottomNavigationView는 메뉴 항목에 따라 화면을 전환하는 역할을 수행하는데 전환되는 화면은 Fragment로 구성합니다.

화면은 하단의 메뉴(BottomNavationView)와 상단의 Fragment를 띄울 Layout으로 구성합니다.

 

이번에는 BottomNavigationView의 구현 방법에 대해 알아보겠습니다.


먼저 실행 결과와 프로젝트의 파일 구성을 보겠습니다.

 

실행 결과
Project 파일 구성


app/build.gradle에서 따로 dependence를 추가할 내용은 없고 뷰 바인딩을 사용하기 위해 viewBinding만 추가해 줍니다.

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

res/menu에 BottomNavigation에 사용할 메뉴를 생성합니다.

 

res 우클릭 → New → Android Resource File

menu_bottom_nav.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/fragment_home"
        android:title="홈"
        android:icon="@drawable/ic_home"/>
    <item
        android:id="@+id/fragment_search"
        android:title="검색"
        android:icon="@drawable/ic_search"/>
    <item
        android:id="@+id/fragment_favorite"
        android:title="즐겨찾기"
        android:icon="@drawable/ic_favorite"/>
    <item
        android:id="@+id/fragment_settings"
        android:title="설정"
        android:icon="@drawable/ic_settings"/>
</menu>

아이콘은 drawable → New → Vector Asset에서 제공되는 기본 아이콘을 사용했습니다.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation_view"
        app:layout_constraintEnd_toEndOf="@+id/bottom_navigation_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation_view"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/menu_bottom_nav"              
        app:labelVisibilityMode="labeled"
        app:itemTextColor="@color/black"
        app:itemIconTint="#2196F3"/>
    
</androidx.constraintlayout.widget.ConstraintLayout>

메뉴 아이템 클릭 시 해당 화면으로 전환을 위해 Fragment를 담을 FrameLayout을 생성합니다.

그리고 xml에 BottomNavigationView 컴포넌트를 생성하고 앞서 만들어 두었던 menu와 연결합니다.

 

BottomNavigationView를 커스텀할 수 있는 많은 속성이 존재하는데 저의 경우 클릭되지 않은 메뉴의 텍스트가 보이지 않아 텍스트를 항상 보이게 하기 위해 labeled로 설정하고 아이콘과 텍스트의 색상만 변경해 줬습니다.

MainActivity

class MainActivity : AppCompatActivity() {
    private val binding: ActivityMainBinding by lazy {
        ActivityMainBinding.inflate(layoutInflater)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        setBottomNavigationView()

        // 앱 초기 실행 시 홈화면으로 설정
        if (savedInstanceState == null) {
            binding.bottomNavigationView.selectedItemId = R.id.fragment_home
        }
    }
    
    fun setBottomNavigationView() {
        binding.bottomNavigationView.setOnItemSelectedListener { item ->
            when (item.itemId) {
                R.id.fragment_home -> {
                    supportFragmentManager.beginTransaction().replace(R.id.main_container, HomeFragment()).commit()
                    true
                }
                R.id.fragment_search -> {
                    supportFragmentManager.beginTransaction().replace(R.id.main_container, SearchFragment()).commit()
                    true
                }
                R.id.fragment_favorite -> {
                    supportFragmentManager.beginTransaction().replace(R.id.main_container, FavoriteFragment()).commit()
                    true
                }
                R.id.fragment_settings -> {
                    supportFragmentManager.beginTransaction().replace(R.id.main_container, SettingsFragment()).commit()
                    true
                }
                else -> false
            }
        }
    }
}

뷰 바인딩을 설정하고 BottomNavigationView에서 제공하는 setOnItemSelectedListener 함수를 통해 화면 전환이 이루어집니다. 메뉴의 아이템이 클릭되면 지정된 Fragment로 화면이 바뀌게 됩니다.

728x90
반응형