COCO World

[안드로이드/Kotlin] BottomNavigation Bar(바텀네비게이션바) 만들기 본문

Android

[안드로이드/Kotlin] BottomNavigation Bar(바텀네비게이션바) 만들기

코코월드주인장 2022. 12. 8. 15:34

 

안녕하세요 ! 

오늘은 프래그먼트를 이용한 페이지 이동을 위해서 빼놓을 수 없는 bottomnavigation bar를 만들어보겠습니다.

위의 완성된 모습은 프래그먼트까지 이어붙여 구현된 모습이에요.

이 페이지에서는 바텀네비게이션을 붙이는 방법까지만 만들어보겠습니다.

 

[ 만드는 순서 ]
1. Implementation gradle 추가
2. navigationBar에 사용할 아이콘 이미지 다운로드
3. 다운한 아이콘이미지 svg -> xml로 변환 
4. selector 적용을 위한 xml파일 생성
5. menu 폴더와 menu파일생성
6. MainActivity.xml에  코드 작성

 

1. Implementation gadle에 추가

  : bottom navigation bar는 안드로이드 jetpack compose 구성요소이기 때문에 종속성을 추가해줘야 합니다.

    build.gradle(module)에 아래 코드를 삽입합니다.

 

// navigation
implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
implementation("androidx.navigation:navigation-ui-ktx:2.5.3")

최신 버전 확인하기 : https://developer.android.com/guide/navigation/navigation-getting-started

2. navigationBar에 사용할 아이콘 이미지 다운로드하기

  : 아이콘으로 사용할 이미지를 저는 svg 파일로 다운 받았습니다. 

    svg파일이 6개인 이유는 클릭 했을때, 안했을때에 각각의 아이콘이 적용되기 때문에 카테고리의 한 아이콘당 2개의 파일이 필요합니다.

   

    또 svg 파일은 xml로 변환작업이 필요하지만 벡터이미지이기 때문에 이미지품질이 좋아서 아이콘으로 사용하기에 안성맞춤이니

    귀찮아도 변환을 해줍시다 !

 

3. 아이콘이미지으로 사용하기위해 아이콘으로 사용할 svg파일을 불러와 xml파일로 변환작업해주기

   :  svg 파일을 변환하는 방법은 이전에 포스팅했기 때문에 링크로 첨부하겠습니다. 

      이 과정을 거치시는 분들은 잠시 방문해주세요 : )

 

https://cocoworld.tistory.com/3

 

[Android/Kotlin]아이콘에 벡터이미지(svg파일)으로 가져와서 변환,적용하기

svg 파일 형식은 벡터이미지이기 때문에 사이즈가 변경되어도 이미지가 깨지지 않아 좋은 품질의 이미지로 제공된다. 그치만 파일크기가 크기 때문에 보편적으로 사용하지는 않고, 아이콘으로

cocoworld.tistory.com

     

 

나는 변환 귀찮아 ! 아이콘인지 알아보기만 하면 돼! 그냥 png나 jpg로 진행시켜 ! 하시는 분들에게 아래 사이트를 추천드립니다.

아이콘 이미지 추천 무료사이트 : https://www.flaticon.com/

 

 

4. 아이콘 클릭 액션효과 적용을 위한 selector xml 생성

  :위의 영상에서 보다시피 클릭했을 때는 색이 적용된 아이콘으로 바뀌고, title명에도 색이 적용되는 모습을 확인할 수 있습니다.

   그러기 위해서는 xml 파일을 생성하여 그 안에서 선택되었을때와 선택되지 않았을때를 정의하여 작성해줘야 합니다.

   

  : drawable > New > Drawable Resource File 생성

아이콘 selector xml 파일 생성

 

 

Root element는 selector로 정의하고, name을 입력한 후 OK 를 눌러 생성해줍니다.

아이콘 카테고리가 총 4개이기 때문에 4개의 파일생성이 필요합니다. 

selector 파일 생성 과정

 

< selector > 안에는 item을 2개 선언해줘야합니다. 아이콘을 클릭했을때와 클릭하지 않았을 때를 정의하기 위해서에요.

    android:drawable = "@보여줄 아이콘 경로"

    android:state_selected = "true" : 아이콘을 선택했을때의 상태로 지정

    android:state_selected = "false" : 아이콘을 선택하지 않았을때의 상태로 지정

   

이런식으로 필요한 아이콘 갯수만큼 파일생성이 필요합니다. 저희는 bottom navigation var카테고리가 3개이기 때문에

총 3개의 selector 파일이 필요해요. 물론 각 파일코드는 아래와 똑같이 상태에 따른 아이콘경로만 바꿔주면 되겠죠?

아래 3개의 파일은 drawable에 담겨져 있어야 합니다.

drawable 경로에 생성한 아이콘selector 파일들

 

4-1. selector_cart_icon.xml 외 2개 파일

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tabbar_cart_on" android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tabbar_cart_off" android:state_selected="false"/>
</selector>

[ selector_cart_icon.xml ]

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tabbar_category_on" android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tabbar_category_off" android:state_selected="false"/>
</selector>

[ selector_category_icon.xml ]

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tabbar_home_on" android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tabbar_home_off" android:state_selected="false"/>
</selector>

[ selector_home_icon.xml ]

 

 

5. menu 폴더 생성 후, 그 안에 navigation_main_menu.xml 파일 생성

    : 바텀 네비게이션 바의 속성을 정의하기 위한 menu 레이아웃이 필요합니다. 

 

     res > New > Android Resource Directory 에서 Menu 폴더 생성

     menu 폴더 > New > Android File 에서 xml 파일 생성

 

5. navigation_main_menu.xml

  : 각 item에 선언한 id값은 추후에 Fragment 연결에 필요하니 기억해둡시다!

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/navigation_category"
        android:icon="@drawable/selector_category_icon"
        android:title="카테고리"/>
    <item android:id="@+id/navigation_home"
        android:icon="@drawable/selector_home_icon"
        android:title="홈"/>
    <item android:id="@+id/navigation_cart"
        android:icon="@drawable/selector_cart_icon"
        android:title="장바구니"/>
</menu>

 

 

여기까지 작성하고나면, Split에 아래와 같은 화면이 보입니다. 

생각한 모양으로 나오지 않아도 당황하지 맙시다. 저희에게 진짜 모습은 MainActivity 레이아웃에 있어요.

 

 

6. MainActivity.xml

   : Bottom Navigation Bar 재료들을 위에서 만들어줬다면 이제 MainActivity.xml에 선언하여 화면으로 구현해줘야합니다.

    프래그먼트는 결국 액티비티 스택 위에 생성되고, 생성된 프래그먼트 만의 생명주기로 스택이 관리되는 특징이 있습니다.

    그래서 바탕이 되는 MainActivity에 네비게이션바를 붙여주고, FragmentContainerView 는 Fragment를 담는 공간입니다.

    

    지금은 바텀 네비게이션을 만드는 과정이지만, FragmentContainerView도 우선 선언은 해줍니다 ! 

    결국엔 프래그먼트를 보여주기 위해서 필요하니까요 :)

    여기서 참조안되는 NavHostFragment와 NavGraph는 우선 무시하세요. Fragment를 만드는 과정에서 생성할 것들입니다.

 

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

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/container_main"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toTopOf="@id/navigation_main"
        app:navGraph="@navigation/main_navigation"/>

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

</androidx.constraintlayout.widget.ConstraintLayout>

 

7. MainActivity

  : 마지막으로 저희가 가져온 아이콘을 적용하기 위해서는 itemIconTintList에 null 처리를 해줘야합니다.

   그렇지않으면, 기본적으로 설정된 itemIconTintList 값들을 불러와 저희가 원하는 모양의 아이콘 이미지처리가 되지 않아요.

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

        // 커스텀 아이콘 사용하기 위한 itemIconTintList setting
        val bottomNavigationView = findViewById<BottomNavigationView>(R.id.navigation_main)
        bottomNavigationView.itemIconTintList = null
        
        }
    }

여기까지 오시게 되면 작고 귀여운 바텀네비게이션바 완성 !

아래와 같은 모습을 확인할 수 있어요.

 

 

맨 위의 영상처럼 완성하기 위해서는 프래그먼트를 만들고, 바텀네비게이션바와 연결해줘야해요.

그럼 이어서 프래그먼트 구현하러 가봅시다 !

 

2022.12.08 - [분류 전체보기] - [안드로이드/Kotlin]프래그먼트 만들기