使用Navigation結(jié)合底部導航欄實現(xiàn)fragment切換

簡介

關(guān)于通過google官方提供的Navigation實現(xiàn)fragment切換,之前已經(jīng)寫了一篇《使用Navigation簡化fragment切換》。本文繼續(xù)深入,結(jié)合底部導航欄實現(xiàn)fragment切換. 本文參考了google官網(wǎng)提供的一個demo,本文基于該demo優(yōu)化過部分內(nèi)容.

實現(xiàn)效果

https://media.giphy.com/media/8Bl37OxaJ4nWs6eYrX/giphy.gif

使用方法

  1. build.gradle中添加依賴
implementation "android.arch.navigation:navigation-common-ktx:1.0.0"
implementation "android.arch.navigation:navigation-fragment-ktx:1.0.0"
implementation "android.arch.navigation:navigation-runtime-ktx:1.0.0"
implementation "android.arch.navigation:navigation-ui-ktx:1.0.0"
  1. 添加navigation文件
  • nav_first.xml
<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_first"
    app:startDestination="@+id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.cxyzy.myapplication.FirstFragment"
        tools:layout="@layout/fragment_first" />
</navigation>
  1. nav_second.xml
<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_second"
    app:startDestination="@id/secondFragment">

    <fragment
        android:id="@+id/secondFragment"
        android:name="com.cxyzy.myapplication.SecondFragment"
        tools:layout="@layout/fragment_second" />
</navigation>
  1. 添加底部菜單文件:bottom_nav.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/nav_first"
        android:icon="@drawable/ic_first"
        android:title="@string/first_page" />
    <item
        android:id="@+id/nav_second"
        android:icon="@drawable/ic_second"
        android:title="@string/second_page" />
</menu>
  1. MainActivity (下面代碼中的setupWithNavController是擴展的自定義函數(shù),請查看Demo源代碼下載)
class MainActivity : AppCompatActivity() {

    private var currentNavController: LiveData<NavController>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (savedInstanceState == null) {
            setupBottomNavigationBar()
        }
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle?) {
        super.onRestoreInstanceState(savedInstanceState)
        setupBottomNavigationBar()
    }

    private fun setupBottomNavigationBar() {
        val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)

        val navGraphIds = listOf(R.navigation.nav_first, R.navigation.nav_second)

        // Setup the bottom navigation view with a list of navigation graphs
        val controller = bottomNavigationView.setupWithNavController(
                navGraphIds = navGraphIds,
                fragmentManager = supportFragmentManager,
                containerId = R.id.nav_host_container,
                intent = intent,
                listener = mOnNavigationItemSelectedListener
        )

        // Whenever the selected controller changes, setup the action bar.
        controller.observe(this, Observer { navController ->
            setupActionBarWithNavController(navController)
        })
        currentNavController = controller
    }

    /**
     * Define your own listener for bottom navigation item clicking.
     */
    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.nav_first -> {
                Toast.makeText(this@MainActivity, "firstFragment", Toast.LENGTH_SHORT).show()
                return@OnNavigationItemSelectedListener true
            }
            R.id.nav_second -> {
                Toast.makeText(this@MainActivity, "secondFragment", Toast.LENGTH_SHORT).show()
                return@OnNavigationItemSelectedListener true
            }
        }
        true
    }

    override fun onSupportNavigateUp(): Boolean {
        return currentNavController?.value?.navigateUp() ?: false
    }

    /**
     * Overriding popBackStack is necessary in this case if the app is started from the deep link.
     */
    override fun onBackPressed() {
        if (currentNavController?.value?.popBackStack() != true) {
            super.onBackPressed()
        }
    }
}

代碼說明

底部菜單項和Fragment的對應關(guān)系如下圖,menu的item的id需要和導航文件中navigation的id一樣.


如何增加一個菜單項

  1. 增加Fragment(ThirdFragment)及對應的布局文件(fragment_third.xml)
  2. 仿造nav_first.xml增加navigation文件nav_third.xml
<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_third"
    app:startDestination="@+id/thirdFragment">

    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.cxyzy.myapplication.ThirdFragment"
        tools:layout="@layout/fragment_first" />
</navigation>
  1. 在底部菜單bottom_nav.xml中增加菜單項
<item
        android:id="@+id/nav_third"
        android:icon="@drawable/ic_second"
        android:title="Third Page" />
  1. 修改MainActivity
  • 修改setupBottomNavigationBar函數(shù)
    val navGraphIds = listOf(R.navigation.nav_first, R.navigation.nav_second)
    修改為val navGraphIds = listOf(R.navigation.nav_first, R.navigation.nav_second,R.navigation.nav_third)
  • 修改mOnNavigationItemSelectedListener
    增加
R.id.nav_third -> {
    Toast.makeText(this@MainActivity, "thirdFragment", Toast.LENGTH_SHORT).show()
    return@OnNavigationItemSelectedListener true
}
  1. 修改后效果


源代碼

https://gitee.com/cxyzy1/navigationDemo/tree/master/bottomNavigationView

附錄

  1. navigation官方介紹文檔:
    https://codelabs.developers.google.com/codelabs/android-navigation/#0
  2. google官網(wǎng)demo:
    https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample
  3. 另外一種在navigation中實現(xiàn)fragment復用的方法(第三方提供的,較為復雜一些):
    https://github.com/STAR-ZERO/navigation-keep-fragment-sample.git

關(guān)于我

廈門大學計算機專業(yè) | 前華為工程師
分享編程技術(shù),沒啥深度,但看得懂,適合初學者。
Java | 安卓 | 前端 | 小程序 | 鴻蒙
公眾號:花生皮編程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容