1.前言
最近公司的项目开始出原型图了,虽然还没正式的 UI 出图,但是UI图不会和原型图有太大的差距。而项目中的主页就有类似微信底部的导航栏。在以前可能用线性布局以及对应的权重来实现此功能,而 Android 的现有库中已经有了实现此功能的控件。本着如果有原生的用,就用原生,没有原生就自己实现,自己实现复杂再用第三方库。因此此篇文章用于记录对 BottomNavigationView 的学习,官方的相关文档查看:
https://material.io/components/bottom-navigation
https://material.io/develop/android/components/bottom-navigation
2.引入
使用 BottomNavigationView 需要引入以下包:
implementation 'com.google.android.material:material:<version>'
查看最新版本请访问:https://maven.google.com/web/index.html#com.google.android.material:material,此处可能需要接个梯子。当前最新的稳定版为 1.2.1。
3.使用
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/fl_main_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/bnv_main"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bnv_main"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:itemIconTint="@color/main_selector_bottom_navigation_item"
app:itemTextColor="@color/main_selector_bottom_navigation_item"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="@menu/main_menu_bottom_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
几个重要属性:
app:itemIconTint:指定底部导航栏元素图标的着色方式,默认元素选中时icon颜色为@color/colorPrimary;
app:itemTextColor:指定底部导航栏元素文字的着色方式;
app:menu:使用Menu的形式为底部导航栏指定元素;
main_menu_bottom_navigation.xml 如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="@+id/home"
android:icon="@drawable/main_ic_home_black_24dp"
android:title="@string/main_bottom_navigation_home"
tools:ignore="MenuTitle" />
<item
android:id="@+id/message"
android:icon="@drawable/main_ic_equalizer_black_24dp"
android:title="@string/main_bottom_navigation_msg" />
<item
android:id="@+id/mine"
android:icon="@drawable/main_ic_person_black_24dp"
android:title="@string/main_bottom_navigation_user" />
</menu>
Activity 中的代码:
override fun initView(savedInstanceState: Bundle?) {
var fragmentFirst = ARouter.getInstance().build(RouterPathConstant.Example.PAGER_FIRST)
.navigation() as Fragment
mFragments = mutableMapOf(
R.id.home to fragmentFirst,
)
bnv_main.run {
setOnNavigationItemSelectedListener { menuItem ->
showFragment(menuItem.itemId)
true
}
setOnNavigationItemReselectedListener { menuItem ->
}
mBadgeMsgNum = getOrCreateBadge(R.id.message)
mBadgeMsgNum.maxCharacterCount = 3
mBadgeMsgNum.number = 101
}
if (savedInstanceState == null) {
val initialItemId = R.id.home
bnv_main.selectedItemId = initialItemId
showFragment(initialItemId)
}
}
/*切换 fragment */
private fun showFragment(menuItemId: Int) {
var curFragment = supportFragmentManager.fragments.find {
it.isVisible && it in mFragments.values
}
var targetFragment = mFragments[menuItemId]
if (targetFragment == null) {
when (menuItemId) {
R.id.home -> {
var fragmentFirst =
ARouter.getInstance().build(RouterPathConstant.Example.PAGER_FIRST)
.navigation() as Fragment
mFragments.put(R.id.home, fragmentFirst)
}
R.id.message -> {
var fragmentSecond =
ARouter.getInstance().build(RouterPathConstant.Example.PAGER_SECOND)
.navigation() as Fragment
mFragments.put(R.id.message, fragmentSecond)
}
R.id.mine -> {
var fragmentThird =
ARouter.getInstance().build(RouterPathConstant.Example.PAGER_THIRD)
.navigation() as Fragment
mFragments.put(R.id.mine, fragmentThird)
}
}
targetFragment = mFragments[menuItemId]
}
supportFragmentManager.beginTransaction().apply {
curFragment?.let { if (it.isVisible) hide(it) }
targetFragment?.let {
if (it.isAdded) show(it) else add(R.id.fl_main_container, it)
}
}.commit()
}
效果如图所示: