Learn to share,Share to learn

kotlin 바텀탭 바텀 네비게이션 바 (bottom tabbar/bottom navigation bar) 만들기 본문

간단 개발노트

kotlin 바텀탭 바텀 네비게이션 바 (bottom tabbar/bottom navigation bar) 만들기

Rogue One 2023. 9. 22. 23:04

 

기존 프로젝트에서 바텀 네비게이션 바를 제대로 구현할 일이 생겨서 처음부터 구현했더니 의외로 시행착오를 겪었다.

내가 겪고 해결한 시행착오를 기록한다.

 

기존의 바텀네비게이션은 액티비티에 들어가는 fragment안에 구현을 했었는데,

binding.talkTab.setOnClickListener {
    it.findNavController().navigate(R.id.action_homeFragment_to_talkFragment)
}

binding.storeTab.setOnClickListener {
    it.findNavController().navigate(R.id.action_homeFragment_to_storeFragment)
}
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="3dp"
    app:layout_constraintBottom_toTopOf="@+id/linearLayout">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:background="@color/mainColor"/>



    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"/>



    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"/>


</LinearLayout>

<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="@color/white"
    app:layout_constraintBottom_toBottomOf="parent">

    <ImageView
        android:id="@+id/homeTab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/bottom_hometap" />



    <ImageView
        android:id="@+id/talkTab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/bottom_boardtap" />


    <ImageView
        android:id="@+id/storeTab"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/bottom_control" />

</LinearLayout>

 

두 코드를 보면 알겠지만

이런식이다.

근데 이 코드의 문제점은 프래그먼트 안에 구현을 했기에 탭바들을 둘러보다 뒤로가기 버튼을 누르면 이전에 사용하던 탭바로 돌아가는것이다. 이게 한번이 아니라 지금까지 돌아본 모든 탭바를 거친뒤에야 앱이 꺼진다 ㅋㅋ... 팀원이 예제 코드로 구현하더니 요건 몰랐나보다. 덕분에 홈과 게시판과 프로필사이를 방황했었다.

 

 

문제점으로는


네비게이션 사용방식이 OnClickListener로 findNavController().navigate()를 직접 사용하고 있다는게 첫번째다. 대부분의 앱에서 바텀 네비게이션의 경우 Android의 BottomNavigationView와 함께 NavController를 사용하여 구현하는 것이 일반적인데, 나름의 커스텀을 한다고 이렇게 되었나보다.

바텀 네비게이션 대신 프래그먼트안 버튼으로 네비게이션을 구현했더니 UI/UX도 일관적이지 않았다.

 

 

그래서 메인 액티비티에 바텀네비게이션 뷰를 추가해주었다. 이전 네비게이션 코드는 날려버리고

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottomNavigationView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:menu="@menu/bottom_nav_menu"
    app:itemIconTint="@color/tab_icon_color"
    app:itemTextColor="@color/tab_text_color"
    app:labelVisibilityMode="labeled"
    app:elevation="8dp"
    android:background="@drawable/bottom_nav_background"/>



근데 이럼 좀 예쁘지가 않으니까 좌상단 우상단에 곡률이라도 넣어줘야 겠지?하는 마음에

 

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white"/>
    <corners android:topLeftRadius="16dp" android:topRightRadius="16dp"/>
</shape>

 

이렇게 백그라운드를 먼저 만들고

 

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

</menu>

 

이런식으로 뭐 들어갈지도 res에 정의하고(정의? 아니면 구현? 둘중 무슨 표현이 적절할까)

 

 

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    
    <item android:color="@color/black" android:state_checked="true" />

    <item android:color="@color/gray" />
</selector>

 

선택할애 선택되지 않은애 색깔도 다르게 선택해주도록 res/tab_colors에 따로 탭 컬러를 적용해주었다.

 

<com.google.android.material.bottomnavigation.BottomNavigationView
    ...
    app:itemIconTint="@color/tab_colors"
    app:itemTextColor="@color/tab_colors"
    ...
/>

이렇게 적용하고 나면 

 

findViewById<BottomNavigationView>(R.id.bottomNavigationView).post { val navController = 
findNavController(R.id.fragmentContainerView) 
findViewById<BottomNavigationView>(R.id.bottomNavigationView).setupWithNavController(navController)



메인 액티비티에 작성하여 바텀탭을 마무리 지을수 있다.

이전에는 매인 액티비티가 앱 최상단의 앱 로고보여주는 역할 정도만 하고 프래그먼트가 그안에서 바뀌며 탭 네비게이션을 구현했는데, 이젠 메인 액티비티가 탭바까지 포함하고 안의 프래그먼트가 탭바따라 바뀌는 형식이다.

 

아 마지막으로 자꾸 오류가 나길래 뭔가 했더니 바텀 네비게이션뷰가 다 그려지지 않았는데 그게 메인액티비티와 충돌해서 문제가 생기는거였다ㅠㅠ 이유를 몰라 좀 해맸다