Bottom Navigation using design Library in Android - Kotlin
Introduction:
Let's implement BottomNavigationView in our layout using Design Support Library. First, we have to go through the factors like, when and how to use that.
When to use?
As per Material Design specs, the following criteria is there:
(a) Tabs (TabLayout) - Should be used when there are two navigations.
(b) Bottom Navigation - Should be used when there are 3 to 5 navigations.
(c) Navigation Drawer - Should be used when there are 6 or more navigations.
Also to remember that, Viewpager shouldn't be used with BottomNavigationView. You can read the complete design specs, here.
Also to remember that, Viewpager shouldn't be used with BottomNavigationView. You can read the complete design specs, here.
How to use?
BottomNavigationView have to be added at the bottom of the screen. Also, the following are some of the important attributes:
app:itemBackground - to apply background color
app:itemTextColor - to apply the color for the text of BottomNavigation item.
app:itemIconTint - to apply the color for the icon of BottomNavigation item.
app:menu - to display navigation item (menu file)
Design:
build.gradle
Include the following in app-level gradle's dependencies.
implementation 'com.android.support:design:26.1.0'
bottom_navigation.xml
Since, we can't use ViewPager with BottomNavigation, we have to use Fragment with it. Here, the root layout should be CoordinatorLayout, if you would like to do some more customization like hiding bottom navigation when scrolling down and showing when scrolling up.
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <FrameLayout android:id="@+id/frame" 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/bottomNavigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" app:menu="@menu/navigation_menu" app:itemBackground="@color/colorPrimary" android:foreground="?attr/selectableItemBackground" app:itemIconTint="@android:color/white" app:itemTextColor="@android:color/white" app:elevation="4dp" android:layout_gravity="bottom"/> </android.support.design.widget.CoordinatorLayout>
navigation_menu.xml
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/home" android:title="@string/home" android:icon="@drawable/home" /> <item android:id="@+id/cart" android:title="@string/cart" android:icon="@drawable/cart" /> <item android:id="@+id/notification" android:title="@string/notification" android:icon="@drawable/notification" /> <item android:id="@+id/profile" android:title="@string/profile" android:icon="@drawable/profile" /> </menu>
list_item.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp"> <android.support.v7.widget.CardView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="5dp" android:elevation="3dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:layout_margin="10dp" android:scaleType="centerCrop" android:src="@drawable/user" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:orientation="vertical"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="Name" /> <TextView android:id="@+id/phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="5dp" android:paddingRight="5dp" android:text="453345435" /> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView> </android.support.constraint.ConstraintLayout>
Code:
Bottombar.kt
We have to set OnNavigationItemSelectedListener to BottomNavigation, to fire particular actions while selection. Here I have only changed toolbar title while selection. You can invoke individual Fragment for each selection.
class BottomBar : AppCompatActivity() { lateinit var toolBar: ActionBar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.bottom_navigation) supportActionBar?.let { toolBar = it } toolBar.title = getString(R.string.home) switchContent(HomeFragment()) bottomNavigation.setOnNavigationItemSelectedListener(object : BottomNavigationView.OnNavigationItemSelectedListener { override fun onNavigationItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.home -> { toolBar.title = getString(R.string.home) switchContent(HomeFragment()) return true } R.id.cart -> { toolBar.title = getString(R.string.cart) return true } R.id.notification -> { toolBar.title = getString(R.string.notification) return true } R.id.profile -> { toolBar.title = getString(R.string.profile) switchContent(ProfileFragment()) return true } } return false } }) } private fun switchContent(fragment: Fragment) { val transaction = supportFragmentManager.beginTransaction() transaction.replace(R.id.frame, fragment) transaction.addToBackStack(null) transaction.commit() } }
HomeFragment.kt
class HomeFragment : Fragment() { var list : MutableList<Human> = ArrayList<Human>() lateinit var adapter: RecyclerAdapter override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater!!.inflate(R.layout.recycler, container, false); } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) /** Adding values **/ list.add(Human("Anisha","9876543210")) list.add(Human("Karthik","9876543210")) list.add(Human("Vino","9876543210")) list.add(Human("Percy","95673210")) list.add(Human("Aruvi","9876543210")) list.add(Human("Faritha","9876543210")) list.add(Human("Annabeth","9876543210")) list.add(Human("Jason","95673210")) list.add(Human("Leo","9876543210")) list.add(Human("Piper","9876543210")) list.add(Human("Thalia","9876543210")) list.add(Human("Frank","95673210")) Log.v("list","list=="+list); recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayout.VERTICAL, false) adapter = RecyclerAdapter(activity, list); recyclerView.adapter = adapter } class RecyclerAdapter(val context: Context, val data: MutableList<Human>) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() { override fun onBindViewHolder(holder: ViewHolder?, position: Int) { if (holder != null) holder.bindItems(data.get(position)) } override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder { val v = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false) return ViewHolder(v) } override fun getItemCount(): Int { return data.size } class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) { fun bindItems(map: Human) { itemView.name.text = "Name : " + map.name itemView.phone.text = "Phone : " + map.phone } } } }
Bonus things:
- If you would like to make BottomNavigation to hide when scroll the RecyclerView down and show when scrolling up, you have to include the following class.
class BottomNavigationBehavior : CoordinatorLayout.Behavior<BottomNavigationView>() { private var height: Int = 0 override fun onLayoutChild(parent: CoordinatorLayout?, child: BottomNavigationView?, layoutDirection: Int): Boolean { height = child!!.height return super.onLayoutChild(parent, child, layoutDirection) } override fun onStartNestedScroll(coordinatorLayout: CoordinatorLayout, child: BottomNavigationView, directTargetChild: View, target: View, axes: Int, type: Int): Boolean { return axes == ViewCompat.SCROLL_AXIS_VERTICAL } override fun onNestedScroll(coordinatorLayout: CoordinatorLayout, child: BottomNavigationView, target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, @ViewCompat.NestedScrollType type: Int) { if (dyConsumed > 0) { slideDown(child) } else if (dyConsumed < 0) { slideUp(child) } } private fun slideUp(child: BottomNavigationView) { child.clearAnimation() child.animate().translationY(0f) } private fun slideDown(child: BottomNavigationView) { child.clearAnimation() child.animate().translationY(height.toFloat()) } }
And include the following in OnCreate of BottomBar.kt
val layoutParams = bottomNavigation.getLayoutParams() as CoordinatorLayout.LayoutParams layoutParams.behavior = BottomNavigationBehavior()
- If you would like to disable the shifting animation in BottomNavigation, you can include the following class to accomplish it.
class BottomNavigationHelper { companion object { @JvmStatic fun disableShiftMode(view: BottomNavigationView) { val menuView = view.getChildAt(0) as BottomNavigationMenuView try { val shiftingMode = menuView.javaClass.getDeclaredField("mShiftingMode") shiftingMode.isAccessible = true shiftingMode.setBoolean(menuView, false) shiftingMode.isAccessible = false for (i in 0 until menuView.childCount) { val item = menuView.getChildAt(i) as BottomNavigationItemView item.setShiftingMode(false) // set once again checked value, so view will be updated item.setChecked(item.itemData.isChecked) } } catch (e: NoSuchFieldException) { Log.e("BottomNavigationHelper", "Unable to get shift mode field", e) } catch (e: IllegalAccessException) { Log.e("BottomNavigationHelper", "Unable to change value of shift mode", e) } } } }
And include the following in OnCreate of BottomBar.kt
BottomNavigationHelper.disableShiftMode(bottomNavigation)
Run Application:
(a) Simple (b) Hide/Show (c) Shift disabled
Comments
Post a Comment