以前介紹過jetpack Navigation的基本使用,本篇文章是Navigation系列的第二篇,主要介紹一下如何將Navigation與BottomNavigationView相結合實現多個fragment切換的過程,以wanAndroid的界面爲依據,分三步實現這個過程:android
建立底部導航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
看一下導航欄建立完成以後的效果:動畫
導航欄建立完成以後就該建立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導航圖。
介紹完了如何建立底部導航欄和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
}
複製代碼
看一下最後的效果: