JetPack系列—将Navigation与BottomNavigationView结合使用

以前介绍过jetpack Navigation的基本使用,本篇文章是Navigation系列的第二篇,主要介绍一下如何将Navigation与BottomNavigationView相结合实现多个fragment切换的过程,以wanAndroid的界面为依据,分三步实现这个过程:android

1. 建立底部导航TAB

建立底部导航tab的第一步就是先建立导航菜单,菜单文件的位置位于res-menu目录下,这个菜单定义了每一个tab的标题、图标、颜色等属性。markdown

main_bottom_navigation.xmlapp

<?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/nav_home" android:icon="@mipmap/icon_home" //图标 android:title="首页" //标题文字 app:showAsAction="ifRoom" />
    <item android:id="@+id/nav_quare" android:icon="@mipmap/icon_square" android:title="广场" app:showAsAction="ifRoom" />
    <item android:id="@+id/nav_pub" android:icon="@mipmap/icon_pub" android:title="公众号" app:showAsAction="ifRoom" />
    <item android:id="@+id/nav_ask" android:icon="@mipmap/icon_ask" android:title="问答" app:showAsAction="ifRoom" />
</menu>
复制代码

导航菜单建立完成以后还没法在界面上显示,要想在界面上看到显示效果须要引入BottomNavigationView。BottomNavigationView是谷歌官方的用于显示底部导航的控件,须要注意的是,BottomNavigationView目前最大设置5个tab,这对大部分的APP应该是够用了。mvvm

引入BottomNavigationView以后须要经过其menu属性与刚刚建立的导航菜单关联。ide

<com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_main" android:layout_width="0dp" android:layout_height="50dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:menu="@menu/main_bottom_navigation" android:background="@color/white" app:flow_wrapMode="none" app:labelVisibilityMode="labeled" app:itemBackground="@null" />
复制代码

当item的数量超过三个时默认只有选中项会同时显示文字和图标,其他项只显示图标,labelVisibilityMode=labeled能够打破这个限制。布局

BottomNavigationView默认每一个item点击时都是有水波纹动画的,使用itemBackground=@null能够去掉默认的点击动画。post

看一下导航栏建立完成以后的效果:动画

图片.png

2. 建立Navigation

导航栏建立完成以后就该建立Navigation了,关于Navigation的详细使用能够参考个人另外一篇文章《JetPack系列—Navigation(一)》,这里只作一下简单的介绍。ui

首先第一步就是建立导航图,导航图的位置在res-navigation目录下,也是一个xml文件。this

nav_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph">
</navigation>
复制代码

这是一个空的导航图,接下来建立BottomNavigationView中每一个item对应的fragment文件,而后把每一个fragment都放到导航图中,而且为导航图指定startDestination起始位置。 nav_graph.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph" app:startDestination="@id/nav_home">

    <fragment android:id="@+id/nav_home" android:name="com.example.mvvm_wanandroid.home.HomeFragment" android:label="fragment_home" tools:layout="@layout/fragment_home" />
    <fragment android:id="@+id/nav_quare" android:name="com.example.mvvm_wanandroid.square.SquareFragment" android:label="fragment_square" tools:layout="@layout/fragment_square" />
    <fragment android:id="@+id/nav_pub" android:name="com.example.mvvm_wanandroid.pub.PublicFragment" android:label="fragment_public" tools:layout="@layout/fragment_public" />
    <fragment android:id="@+id/nav_ask" android:name="com.example.mvvm_wanandroid.ask.AskFragment" android:label="fragment_ask" tools:layout="@layout/fragment_ask" />
</navigation>
复制代码

完成这几步以后还须要将导航图关联到activity中,通常指的fragment所在的activity。这时候就会用到另一个控件FragmentContainerView了, FragmentContainerView 位于androidx.fragment.app包下面,是专门为Fragment设计的自定义布局,能够看做是fragment的容器。

在activity中引入fragmentcontainerview:

<androidx.fragment.app.FragmentContainerView android:id="@+id/nav_host_fragment" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:name="androidx.navigation.fragment.NavHostFragment" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" app:layout_constraintTop_toBottomOf="@+id/main_toolbar"/>
复制代码

name属性必定要定义成androidx.navigation.fragment.NavHostFragment,同时须要关联nav_graph导航图。

3. 将Navigation与BNV关联

介绍完了如何建立底部导航栏和navigation以后要想实现最终的效果就要将这两个组件关联到一块儿。

private var binding:ActivityMainBinding?=null
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = DataBindingUtil.setContentView(this,R.layout.activity_main)
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.findNavController()
    NavigationUI.setupWithNavController(binding!!.navMain,navController)
复制代码

这里使用了NavigationUI.setupWithNavController将Navigation与BottomNavigationView关联到一块儿,当点击导航的每一个item时就能够切换fragment了。有一点要注意就是若是咱们同时实现了BottomNavigationView的 onNavigationItemSelected方法会致使上面的方式失效,这个时候能够把关联的操做放到onNavigationItemSelected回调方法中执行。

private lateinit var navController:NavController
override fun onNavigationItemSelected(item: MenuItem): Boolean {
    NavigationUI.onNavDestinationSelected(item, navController)
    return true
}
复制代码

看一下最后的效果:

图片.png

相关文章
相关标签/搜索