티스토리 뷰

반응형

안드로이드에서 하단 바로 선택할 수 있는 게 Bottom Navigation View입니다.

 

 

시작하기

 

build.gradle에 아래 정의를 추가해줍니다.

implementation 'com.android.support:design:29.0.0'
implementation 'com.google.android.material:material:1.2.0'

 

 

menu 만들기

bottom navigation view에 필요한 menu를 만들도록 하겠습니다.

 

 

 

 

 

 

New > Android Resource File을 클릭합니다.

 

 

Resource type을 Menu로 선택 후 생성합니다.

 

 

그리고 아래와 같이 코드를 작성해 줍니다.

<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/page_home"
        android:enabled="true"
        android:icon="@drawable/icon_home"
        android:title="홈"/>

    <item
        android:id="@+id/page_tv"
        android:enabled="true"
        android:icon="@drawable/icon_tv"
        android:title="TV"/>

    <item
        android:id="@+id/page_calendar"
        android:enabled="true"
        android:icon="@drawable/icon_calendar"
        android:title="일정"/>
</menu>

icon은 Vector Asset을 추가하였습니다.

 

 

 

XML 코드 작성하기

activity_main의 코드를 아래와 같이 작성하였습니다.

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

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
        />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottom_navigation_menu"
        app:itemBackground="@android:color/white"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

 

BottomNavigationView에 menu로 만들어둔 menu를 추가하면 됩니다.

 

BottomNavigationView와 Fragment를 적용시킬 Layout에 id를 만들어 줍니다.

 

 

 

Kt 코드 작성하기

이제 코드를 작성하겠습니다.

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

        bottomNavigationView.setOnNavigationItemSelectedListener(this)

        supportFragmentManager.beginTransaction().add(R.id.linearLayout, HomeFragment()).commit()
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {

        when(item.itemId) {
            R.id.page_home -> {
                supportFragmentManager.beginTransaction().replace(R.id.linearLayout , HomeFragment()).commitAllowingStateLoss()
                return true
            }
            R.id.page_tv -> {
                supportFragmentManager.beginTransaction().replace(R.id.linearLayout, TVFragment()).commitAllowingStateLoss()
                return true
            }
            R.id.page_calendar -> {
                supportFragmentManager.beginTransaction().replace(R.id.linearLayout, CalendarFragment()).commitAllowingStateLoss()
                return true
            }
        }

        return false
    }
}

 

BottomNavigationView.OnNavigationItemSelectedListener를 사용하여 onNavigationItemSelected를 오버라이드 하여 사용하면 됩니다.

 

선택된 id 마다 fragment를 보여주었습니다.

 

replace에서 처음에 들어가는 값은 위의 LinearLayout의 id값입니다.

바꾸고 싶은 layout의 id 값을 넣어주면 됩니다.

 

마지막으로 Fragment를 넣어주면 됩니다.

 

 

실행하면 아래와 같이 동작합니다.

 

 

 

Bottom Navigation View 메뉴 색상 바꾸기

기본으로 제공되는 색상 말고 다른 색상이 쓰고 싶어 아래와 같이 변경하였습니다.

 

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottom_navigation_menu"
        app:itemBackground="@android:color/white"
        app:itemIconTint="@android:color/black"
        app:itemTextColor="@android:color/black"
        />

 

실행을 하면 아래와 같이 동작합니다.

 

 

 

 

메뉴가 선택되었을 때와 선택되지 않았을 때 색이 같은 것을 확인할 수 있습니다.

 

선택될 때의 색과 선택되지 않았을 때의 색을 적용해줘야 됩니다.

 

 

 

New > Android Resource File을 누릅니다.

 

Resource type을 Color로 선택 후에 생성을 합니다.

 

 

그리고 아래와 같이 코드를 작성해 줍니다.

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

 

 

itemIconTint와 itemTextColor를 아래와 같이 수정후 실행합니다.

app:itemIconTint="@color/bottom_navigation_item_selector"
app:itemTextColor="@color/bottom_navigation_item_selector"

 

 

메뉴 창이 선택되었을 때만 색이 바뀌는 것을 확인할 수 있습니다.

 

 

 

Bottom Navigation View에 ViewPager2 적용하기

메뉴를 선택했을 때 이동할 뿐만 아니라 슬라이드 하여 이동하고 싶을 때 ViewPager를 사용하면 됩니다.

 

 

먼저 build.gralde에 아래 코드를 추가해줍니다.

implementation 'androidx.viewpager2:viewpager2:1.0.0'

 

 

activity_main의 xml을 아래와 같이 수정해줍니다.

LinearLayout을 ViewPager2로 바꾸었습니다.

<?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.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
        />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottom_navigation_menu"
        app:itemBackground="@android:color/white"
        app:itemIconTint="@color/bottom_navigation_item_selector"
        app:itemTextColor="@color/bottom_navigation_item_selector"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

ViewPager Adapter

 

먼저 ViewPager에 사용할 Adapter를 추가해주겠습니다.

class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
   
   override fun onCreate(savedInstanceState: Bundle?) {
   
       ...

        viewPager.adapter = ViewPagerAdapter(supportFragmentManager, lifecycle)
    }
    
    ...

    private inner class ViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fragmentManager, lifecycle) {

        override fun getItemCount(): Int = 3

        override fun createFragment(position: Int): Fragment {

            return when (position) {
                0 -> HomeFragment()
                1 -> TVFragment()
                2 -> CalendarFragment()
                else -> error("No Fragment")
            }
        }
    }
}

 

FragmentStateAdapter를 상속받는 ViewPagerAdapter Class를 만들었습니다.

 

getItemCount에는 메뉴의 개수를 넣었고,

createFragment에서는 position에 따라 Fragment를 반환하는 코드를 작성하였습니다.

 

 

Fragment에서 사용할 때에는 아래와 같이 사용하면 됩니다.

viewPager.adapter = ViewPagerAdapter(this)

private inner class ViewPagerAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {}

 

 

 

Change Callback

 

ViewPager에 Change Callback을 적용해야 됩니다.

class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
    override fun onCreate(savedInstanceState: Bundle?) {
    
        ...
        
        viewPager.registerOnPageChangeCallback(ViewPagerPageChangeCallback())
    }
    
    ...

    private inner class ViewPagerPageChangeCallback : ViewPager2.OnPageChangeCallback() {

        override fun onPageSelected(position: Int) {

            bottomNavigationView.selectedItemId = when(position) {
                0 -> R.id.page_home
                1 -> R.id.page_tv
                2 -> R.id.page_calendar
                else -> error("No id")
            }
        }
    }
    
    ...
}

 

ViewPager2.OnPageChangeCallback을 상속받는 ViewPagerPageChangeCallback Class를 만들었습니다.

 

onPageSelected를 오버라이드 하여 position에 따른 메뉴를 선택해주는 코드를 작성하였습니다.

 

registerOnPageChangeCallback에 만든 Class를 Callback으로 등록해줍니다.

 

 

 

onNavigationItemSelected

 

마지막으로 Bottom Navigation View의 onNavigationItemSelected를 수정하면 됩니다.

override fun onNavigationItemSelected(item: MenuItem): Boolean {

    when(item.itemId) {
        R.id.page_home -> {
            viewPager.currentItem = 0
            return true
        }
    R.id.page_tv -> {
            viewPager.currentItem = 1
            return true
        }
        R.id.page_calendar -> {
            viewPager.currentItem = 2
            return true
        }
    }

    return false
}

 

선택되었을 때 ViewPager의 item 값을 바꾸어주는 코드를 작성하였습니다.

 

 

실행하면 아래와 같이 동작합니다.

 

반응형
댓글