안드로이드 하단 탭, BottomNavigationView로 구현하기

28110 단어 UIandroidUI

안녕하세요, 오늘은 안드로이드 하단 탭을 구현하는 방법을 알아보겠습니다.

아래는 완성본입니다.


하단 탭을 구현하기 전, 메뉴에 따라 보여줄 프래그먼트를 구성해줍니다.

저는 아래와 같이 탭 이름만 화면에 나타나는 간단한 홈, 갤러리, 마이페이지 프래그먼트를 구현하였습니다.

class HomeFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false)
    }

    companion object {
        const val TAG = "HomeFragment"
        fun newInstance() =  HomeFragment()
    }
}
<!-- res/layout/fragment_home.xml -->

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeFragment">

    <TextView
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/home" />

</FrameLayout>

필요한 프래그먼트를 모두 생성했으면 아래와 같이 메뉴 리소스 파일을 만들고, 탭을 구성할 메뉴 아이템을 작성해주세요.
<!-- res/menu/menu_bottom_navigation -->

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_home"
        android:title="@string/home"
        android:icon="@drawable/ic_home" />

    <item
        android:id="@+id/menu_gallery"
        android:title="@string/gallery"
        android:icon="@drawable/ic_gallery" />

    <item
        android:id="@+id/menu_my_page"
        android:title="@string/my_page"
        android:icon="@drawable/ic_my_page" />
</menu>

그다음, 하단 탭을 구현할 액티비티에 FragmentContainerViewBottomNavigationView를 배치해주세요.

<!-- res/layout/activity_main.xml -->

<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">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottomNav"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNav"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

BottomNavigationView의 속성에 처음에 작성했던 메뉴 아이템들을 추가시켜줍니다. (app:menu 속성)

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNav"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:menu="@menu/menu_bottom_navigation"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

마지막으로, 하단 탭에 ItemSelectedListener를 설정해주고, 선택한 메뉴에 따라 적절한 프래그먼트가 보일 수 있도록 설정해줍니다.

class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListener {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        initView(ActivityMainBinding.inflate(layoutInflater))
    }

    private fun initView(binding: ActivityMainBinding) = with(binding) {
        setContentView(root)
        bottomNav.setOnItemSelectedListener(this@MainActivity)
        bottomNav.selectedItemId = R.id.menu_home
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean =
        when (item.itemId) {
            R.id.menu_home -> {
                showFragment(HomeFragment.TAG)
                true
            }
            R.id.menu_gallery -> {
                showFragment(GalleryFragment.TAG)
                true
            }
            R.id.menu_my_page -> {
                showFragment(MyPageFragment.TAG)
                true
            }
            else -> false
        }

    private fun showFragment(tag: String) {
        // 기존 프래그먼트 숨기기
        supportFragmentManager.fragments.forEach {
            supportFragmentManager.beginTransaction().hide(it).commit()
        }

        // 선택한 프래그먼트 보여주기
        supportFragmentManager.findFragmentByTag(tag)?.let {
            supportFragmentManager.beginTransaction().show(it).commit()
        } ?: createFragmentByTag(tag).let {
            supportFragmentManager.beginTransaction().add(R.id.fragmentContainer, it, tag).commit()
        }
    }
    
    private fun createFragmentByTag(tag: String): Fragment = when (tag) {
        HomeFragment.TAG -> HomeFragment.newInstance()
        GalleryFragment.TAG -> GalleryFragment.newInstance()
        MyPageFragment.TAG -> MyPageFragment.newInstance()
        else -> throw Exception("유효하지 않은 TAG 입니다.")
    }
}

이렇게 하면 선택한 메뉴에 따라 프래그먼트가 변경되는 하단 바를 구현할 수 있습니다.

만약 틀린 부분 있다면 댓글로 알려주세요 😊

좋은 웹페이지 즐겨찾기