作为前端开发第一次接触安卓项目,那是一看一个不吱声,一看一个迷糊糊~
页面底部导航栏基本所有APP中最常见的布局,这里先介绍下我了解到的安卓实现底部导航的几种方式:
- ViewPager + RadioGroup + Fragment
- View + Fragment
- ViewPager + TabLayout + Fragment
- BottomNavigationView + Fragment
目前简单了解以上几种实现方式大差不差,基本都是使用菜单栏布局家动态变更fragment管理实现的,期中ViewPager主要实现的是用户滑动手势切换菜单栏的功能,根据项目需求可以组合使用。
一开始尝试了TabLayout + Fragment,也实现了切换功能,但是发现要在其中增加图标需要自定义item搞定,比较麻烦。初学者没有太多的这方面知识储备我的项目中菜单又是比较固定的,所以这里面选择了第四种BottomNavigationView + Fragment
这里废话有点多,下面我们直接进入主题;
先说下我这里开发是以Kotlin为主开发语言,Java版本18,Gradle版本8.2.1,SDK版本34;
下图为我的基本结构,Layout为一个主入口和四个Fragment,menu为我们需要的底部布局菜单配置,具体创建方法这里就不在赘述了;
图1
首先需要在activity_main中实现一下我们要的基础布局,添加FrameLayou和BottomNavigationView,FrameLayou容器这里主要用于承载动态的Fragment页面,BottomNavigationView组件用于实现底部TAB栏目 ,这里的BottomNavigationView组建中menu引用菜单配置
<FrameLayout
android:id="@+id/frameContentView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FFF7F8F9"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:menu="@menu/menu_tabbar"/>
menu菜单配置如下
<item
android:id="@+id/tab_home"
android:icon="@mipmap/mall_icon"
android:title="@string/tab_home"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/tab_sort"
android:icon="@mipmap/link_icon"
android:title="@string/tab_sort"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/tab_bag"
android:icon="@mipmap/user_icon"
android:title="@string/tab_bag"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/tab_user"
android:icon="@mipmap/user_icon"
android:title="@string/tab_user"
app:showAsAction="ifRoom"/>
到这里我们就实现了一个基本布局
上图看到菜单栏目和 Fragment容器,但是当前FrameLayou中为空的,这里需要我们准备对应菜单数量的Fragment,创建Fragment的方法也就不在赘述了,我们直接在程序入口时进行Fragment管理和初始化填充
// 定义私有变量获取到Fragment管理
private val fragmentManager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 启动beginTransaction事务进行管理Fragment
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.replace(R.id.frameContentView, HomeFragment())
fragmentTransient.commit()
}
再次运行项目,我们发现内容已经显示出来了,FrameLayou初始化填充也就完成了~
下面我们就要实现点击底部菜单栏进行FrameLayou内容的切换
override fun onCreate(savedInstanceState: Bundle?) {
// 为BottomNavigationView添加监听事件
findViewById<BottomNavigationView>(R.id.bottomNavView).setOnItemSelectedListener(onBottomNavigationView)
}
// 添加私有事件获取BottomNavigationView的变化
private val onBottomNavigationView = NavigationBarView.OnItemSelectedListener {
when (it.itemId) {
R.id.tab_home ->{
// 根据Tab栏目id变化切换不同的Fragment
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.apply {
replace(R.id.frameContentView, HomeFragment())
commit()
}
return@OnItemSelectedListener true
}
R.id.tab_sort ->{
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.apply {
replace(R.id.frameContentView, SortFragment())
commit()
}
return@OnItemSelectedListener true
}
R.id.tab_bag ->{
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.apply {
replace(R.id.frameContentView, BagFragment())
commit()
}
return@OnItemSelectedListener true
}
R.id.tab_user ->{
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.apply {
replace(R.id.frameContentView, UserFragment())
commit()
}
return@OnItemSelectedListener true
}
}
false
}
到这里也就实现了Fragment + BottomNavigationView的全部功能,但是发现代码有些太过于冗余,可以在此基础上在将更新Fragment定义成一个单独方法实现并使用apply进行代码精简,废话不说直接上我精简后的完整代码
private val fragmentManager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 初始化Fragment
replaceFragment(HomeFragment())
// 监听BottomNavigationView
findViewById<BottomNavigationView>(R.id.bottomNavView).apply {
setOnItemSelectedListener(onBottomNavigationView)
}
}
// 定义Fragment实务方法
private fun replaceFragment(fragment: Fragment){
val fragmentTransient = fragmentManager.beginTransaction()
fragmentTransient.apply {
replace(R.id.frameContentView, fragment)
commit()
}
}
// BottomNavigationView监听事件
private val onBottomNavigationView = NavigationBarView.OnItemSelectedListener{
when (it.itemId) {
R.id.tab_home ->{
// 调用统一方法进行更新Fragment
replaceFragment(HomeFragment())
return@OnItemSelectedListener true
}
R.id.tab_sort ->{
replaceFragment(SortFragment())
return@OnItemSelectedListener true
}
R.id.tab_bag ->{
replaceFragment(BagFragment())
return@OnItemSelectedListener true
}
R.id.tab_user ->{
replaceFragment(UserFragment())
return@OnItemSelectedListener true
}
}
false
}