Android BottomNavigationView 사용하기



개인 광고 영역

안드로이드 Support Library 25 버전부터 BottomNavigationView을 사용할 수 있게 되었습니다.

BottomNavigationView는 다음과 같이 하단에 포함되는 View를 말합니다.

bottom_sample_01

  • 해당 예제 코드는 GitHub의 블로그 예제에 포함되어 있으며, KotlinJava로 구성되어 있으며, MVP 구조로 작성하였습니다.


BottomNavigationView API 문서


BottomNavigationView 적용하기

BottomNavigationView는 크게 2가지 View 정의가 필요합니다.

  • BottomNavigationView에서 사용할 menu.xml을 정의합니다.
  • BottomNavigationView을 사용할 xml에 layout resource에 BottomNavigationView을 정의합니다.

gradle에 다음과 같이 support design 라이브러리를 추가합니다.

버전은 25.0.0 이상을 사용하여야 합니다.

compile "com.android.support:design:25.0.0"


menu.xml 정의하기

BottomNavigationView에서 사용할 메뉴를 정의합니다.

이때 주의할 부분이 있습니다. item을 최소 3개 이상 추가하셔야 합니다.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_one"
        app:showAsAction="ifRoom"
        android:enabled="true"
        android:icon="@android:drawable/ic_dialog_info"
        android:title="@string/selection_home" />
    <item
        android:id="@+id/action_two"
        app:showAsAction="ifRoom"
        android:icon="@android:drawable/ic_dialog_info"
        android:title="@string/selection_daily_box_office" />
    <item
        android:id="@+id/action_three"
        app:showAsAction="ifRoom"
        android:enabled="true"
        android:icon="@android:drawable/ic_dialog_info"
        android:title="@string/selection_weekly_box_office" />
</menu>

2개만 추가한다면 다음과 같은 화면을 볼 수 있게 됩니다.

  • 가이드상 3개 이상에서 사용하여야 합니다.

bottom_sample_02


layout resource에 정의하기

BottomNavigationView을 아래와 같이 적용이 가능합니다.

위에서 정의한 menu는 다음과 같이 추가할 수 있습니다.

  • app:menu="@menu/xml 파일명"

item의 background 정의를 다음과 같이 할 수 있습니다.

  • app:itemBackground="color code"
<android.support.design.widget.CoordinatorLayout>
	<!-- 생략 -->
	<android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:itemBackground="@color/colorPrimary"
        app:itemIconTint="@color/bottom_section_color"
        app:itemTextColor="@color/bottom_section_color"
        app:layout_behavior="tech.thdev.app.view.BottomNavigationBehavior"
        app:menu="@menu/bottom_navigation_main" />
			</android.support.design.widget.CoordinatorLayout>

각각 이미지와 텍스트에 대한 색상 값을 정의할 수 있습니다.

  • app:itemIconTint="color code"
  • app:itemTextColor="color code"

이때 아래와 같이 표현되도록 하려면 color 코드를 별도로 정의해주셔야 합니다.

color을 별도로 다음과 같이 정의한 상태라서 아래와 같이 표현됩니다.

  • state_checked가 선택된 상태를 말합니다.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="#51032d" />
    <item android:color="#CFD8DC"  />
</selector>

위와 같이 정의한 파일을 itemIconTintitemTextColor에서 사용하게 됩니다.

bottom_sample_01


menu item click 정의하기

menu로 정의하긴 했지만 실제 메뉴가 아닌 BottomNavigationView을 통해서 정의한 부분입니다.

그래서 다음과 같이 Java 코드에서 item에 대한 click을 정의해주어야 합니다.

itemgetItemId을 불러와서 action 정의를 처리하시면 되겠습니다.

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_one:
                        return true;
                    case R.id.action_two:
                        return true;
                    case R.id.action_three:
                        return true;
                }
                return false;
            }
        });


BottomNavigationView을 적용하는데 있어 피해야 할 스타일

구글의 문서 정의에서 볼 수 있는 부분으로 아래와 같이 아이템의 색상을 단색이 아닌 여러 색을 처리하지 않는 것을 권장하고 있습니다.

components_bottomnavigation_style8

그 외에

  • 1줄을 넘어가는 텍스트 사용하지 말 것
  • 바텀 메뉴 누를 경우 ViewPager 상에 swipe 에니메이션 처리하지 말 것
  • 스크롤이 발생할 경우 바텀 메뉴는 숨김 처리하며 다시 위로 올라오면 노출할 것
  • 가이드상 3개 이상에서 사용하여야 합니다.
  • 4~5개일 경우는 이미지로만 노출할 것

등의 조건이 달립니다.


Bottom Behavior 정의하기

위의 피해야 할 스타일 중 마지막인

  • 스크롤이 발생할 경우 바텀 메뉴는 숨김 처리하며 다시 위로 올라오면 노출할 것

위의 조건은 다음의 에니메이션 처리와 같아야 합니다.

Behavior

이를 위해서 다음의 글을 참고하여 해당 Behavior 정의를 그대로 사용하였습니다.

그래서 다음과 같이 Behavior 정의만 하면 되겠습니다.

<android.support.design.widget.BottomNavigationView
		app:layout_behavior="tech.thdev.app.view.BottomNavigationBehavior" />


Swipe 발생 시 하단의 버튼 선택하기

가이드랑은 맞지 않지만 Swipe 발생할 경우 다음과 같이 작업이 가능합니다.

BottomNavigation의 API를 보면 딱 Swipe에 대한 대응 같은 건 존재하지 않고, current Item 선택하는 것도 다음과 같이 처리가 가능합니다.

내부의 getMenu를 불러오고 해당 position의 아이템을 가져와 setChecked 상태를 변경하는 방법입니다.

/**
 * BottomNavigation Prev
 */
private MenuItem prevBottomNavigation;

@Override
public void onPageSelected(int position) {
		if (prevBottomNavigation != null) {
				prevBottomNavigation.setChecked(false);
		}
		prevBottomNavigation = bottomNavigationView.getMenu().getItem(position);
		prevBottomNavigation.setChecked(true);
}


완성된 샘플

완성된 샘플은 아래와 같습니다.

ViewPager를 활용해서 만들었고, 원래 가이드대로의 ViePager 이동에 대한 부분은 처리하지 않았습니다.

가이드상으로는 ViewPager 간의 이동이 아닌 페이지 단위로 이동이 일어나야겠죠. + 에니메이션

bottomNavigation

위의 샘플은 Target API 25로 작성하였고, Support Library 25가 추가된 상태입니다.

해당 사이트에 접근하셔서 API 키를 발급받아

local.properties에 다음과 같이 코드를 추가해주시면 되겠습니다.

kobis_api_key="발급받은 API Key"


마무리

BottomNavigationView가 구글의 옛날 가이드 대로라면 좋은 메뉴가 아닙니다.

  • SW 내비게이션 버튼이 존재하고, 이와 겹칠 수 있어서 기존에는 사용하지 말라고 가이드 한 적이 있습니다.

하지만… Material 디자인이 나오고, 많은 변화가 있는 듯합니다.

실제로 적용해보니 적용하는 부분은 어렵지 않은데 커스텀을 통해서 만드는 것과 차이가 크지 않긴 합니다.

제한이 많기도 합니다. 위에 설명 중 2개만 추가했을 때 공백이 발생할 수 있음을 말하였듯이 맞지 않는 부분도 존재합니다.

그리고 CoordinatorLayout을 사용한 상태로 BottomNavigationView을 추가해주면 layout_anchor을 추가해주지 않으면 하단에 붙지 않습니다.

FloatingActionButton을 함께 사용하기도 까다롭긴 합니다.

좀 더 쉽게 적용할 수 있게 나왔으면 합니다.

추가로 Google에서 작성한 BottomNavigationView의 내부를 열어보면 Presenter를 포함하고 있음을 보아 MVP 구조로 작업되어 있으니, 살펴보시면 좋을 것 같습니다.



About Taehwan

My name is Taehwan Kwon. I have developed Android for 6 years and blog has been active for eight years.

Comments