关于android:Navigation-这么好用的导航框架你确定不来看看

前言

🏀什么是Navigation?官网文档的话有点不容易让人了解。所以,这里用我本人的话来总结一下,咱们在解决Fragment是须要通过写Fragment的事务去操作Fragment的,而Navigation的呈现是为了解决咱们之前开发的一些痛点。Navigation次要用于实现Fragment代替Activity的页面导航性能,让Fragment可能轻松的实现跳转与传递参数,咱们能够通过应用Navigation,让Fragment代替android我的项目中绝大多数的Activity。但须要留神的是在应用Navigation切换页面生命周期的变动状况,防止开发过程中踩坑。

🌟官网文档:https://developer.android.goo…

🌟navigation我的项目地址:https://github.com/googlecode…

💡本文Demo地址:https://github.com/taxze6/Jet…

应用Navigation具备什么劣势?

  • 解决Fragment事务
  • 默认状况下,能正确处理往返操作
  • 为动画和转换提供标准化资源
  • 实现和解决深层链接
  • 包含导航界面模式,例如抽屉式导航栏和底部导航,咱们只须要实现大量的代码编写
  • Safe Args – 可在指标之间导航和传递数据时提供类型平安的Gradle插件
  • ViewModel反对 – 您能够将ViewModel的范畴限定为导航图,以在图标的指标之间共享与界面相干的数据

如何应用Navigation呢?

Navigation目前仅AndroidStudio 3.2以上版本反对,如果您的版本有余3.2,请点此下载最新版AndroidStudio(2202年了应该没有人还在用3.2以下的版本吧!🐤)

在开始学习Navigation组件之前,咱们须要先对Navigation次要组成部分有个简略的理解,Navigation由三局部组成:

  • Navigation graph:一个蕴含所有导航相干信息的 XML 资源
  • NavHostFragment:一种非凡的Fragment,用于承载导航内容的容器
  • NavController:治理利用导航的对象,实现Fragment之间的跳转等操作

上面咱们正式开始学习Navigation啦

第一步:增加依赖

//project的Navigation依赖设置
dependencies {
  //文章公布时的最新稳固版本:
  def nav_version = "2.4.2"
​
  // 应用java作为开发语言增加上面两行:
  implementation "androidx.navigation:navigation-fragment:$nav_version"
  implementation "androidx.navigation:navigation-ui:$nav_version"
​
  // Kotlin:
  implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
  implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
​
//Compose版本:
implementation "androidx.navigation:navigation-compose:$nav_version"

第二步:创立导航图

右键点击res目录,而后顺次抉择NewAndroid Resource Directory。此时零碎会显示 New Resource Directory对话框。Directory name输出你的文件夹名(个别为navigation),Resource type抉择navigation

右键navigation文件夹,而后newNavigation Resource FileFile name中输出名称(罕用nav_graph_main或nav_graph

第三步:创立Fragment

为了让跳转更加的丰盛,咱们这里创立三个Fragment

咱们能够本人手动创立:

FirstFragment:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">
​
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="hello world" />
</FrameLayout>
class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }
}

另外创立两个和FirstFragement一样的:SecondFragmentThirdFragment

咱们也能够通过Navigation graph创立

咱们在新建好的nav_graph_main.xml下,在右上角切换到Design模式,而后在Navigation Editor中,点击Create new destination,抉择所须要的Fragment后,点击Finish,你就会发现Fragment曾经呈现在咱们能够拖动的面板中了。

第四步:将Fragment拖入面板并进行跳转配置

只须要在Navigation Editor中双击想要的Fragment就会被退出到面板中啦。

点击其中一个Fragment,你会发现,在他的左边会有一个小圆点,拖曳小圆点指向想要跳转的那个Fragment,咱们这里设置FirstFragmentSecondFragmentThirdFragmentFirstFragment


咱们将nav_graph_main.xml切换到Code下,咱们来解读一下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_main"
    app:startDestination="@id/firstFragment">
    <fragment
        android:id="@+id/firstFragment"
        android:name="com.taxze.jetpack.navigation.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secondFragment2"
            app:destination="@id/secondFragment" />
    </fragment>
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.taxze.jetpack.navigation.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" >
        <action
            android:id="@+id/action_secondFragment_to_thirdFragment2"
            app:destination="@id/thirdFragment" />
    </fragment>
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.taxze.jetpack.navigation.ThirdFragment"
        android:label="fragment_third"
        tools:layout="@layout/fragment_third" >
        <action
            android:id="@+id/action_thirdFragment_to_firstFragment"
            app:destination="@id/firstFragment" />
    </fragment>
</navigation>
  • navigation是根标签,通过startDestination配置默认启动的第一个页面,这里配置的是firstFragment,咱们能够在代码中手动改mainFragment(启动时的第一个Fragment),也能够在可视化面板中点击Fragment,再点击Assign Start Destination,同样能够批改mainFragment

  • fragment标签就代表这是一个Fragment
  • action标签定义了页面跳转的行为,就是上图中的每条线,destination定义跳转的指标页,还能够退出跳转时的动画

💡留神:在fragment标签下的android:name属性,其中的包名的是否正确申明

第五步:解决MainActivity

编辑MainActivity的布局文件,在布局文件中增加NavHostFragment。咱们须要通知NavigationActivity,咱们的Fragment展现在哪里,所以NavHostFragment其实就是导航界面的容器

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
​
    <fragment
        android:id="@+id/nav_host_fragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
  • fragment标签下的android:name是用于指定NavHostFragment
  • app:navGraph是用于指定导航视图的
  • app:defaultNavHost=true是在每一次Fragment切换时,将点击记录在堆栈中保存起来,在须要退出时,按下返回键后,会从堆栈拿到上一次的Fragment进行显示。然而在某些状况下,这样的操作不是很敌对,不过好在咱们只须要将app:defaultNavHost=true改为app:defaultNavHost=false或者删除这行即可。在其为false的状况下,无论怎么切换Fragment,再点击返回键就都间接退出app。当然咱们也能够对其堆栈进行监听,从而来实现,点击一次返回键回到主页,再点击一次返回键退出app

批改MainActivity

咱们重写了onSupportNavigateUp,示意咱们将Activityback点击事件委托进来

class MainActivity : AppCompatActivity() {
    override  fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
​
    override fun onSupportNavigateUp(): Boolean {
        return findNavController(R.id.nav_host_fragment).navigateUp()
    }
}

第六步:解决Fragment的对应跳转事件

Fragment布局:给一个按钮用于跳转,一个TextView用于标识,三个Fragment布局雷同

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">
​
    <Button
        android:id="@+id/firstButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="点击跳转到第二个fragment" />
​
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/hello_first_fragment" />
​
</FrameLayout>
​
//secondFragment中退出:
<Button
        android:id="@+id/firstButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="点击跳转到第三个fragment" />
​
//thirdFragment中退出:
<Button
        android:id="@+id/firstButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="返回第一个fragment" />

②配置Fragment对应的跳转事件

class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }
   
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.firstButton).apply {
         setOnClickListener {
          it.findNavController().navigate(R.id.action_firstFragment_to_secondFragment2)
         }
        }
    }
}
​
//secondFragment中退出:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.firstButton).apply {
         setOnClickListener {
           it.findNavController().navigate(R.id.action_secondFragment_to_thirdFragment2)
         }
        }
}
​
//thirdFragment中退出:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        view.findViewById<Button>(R.id.firstButton).apply {
            setOnClickListener {
              it.findNavController().navigate(R.id.action_thirdFragment_to_firstFragment)
            }
        }
}

其中的R.id.action_firstFragment_to_secondFragment2这样的标识,是在nav_graph_main.xmlaction标签下配置的。

<action
    android:id="@+id/action_firstFragment_to_secondFragment2"
    app:destination="@id/secondFragment" />

③最初的效果图:

跳转动画&自定义动画

咱们会发现,刚刚的例子中,咱们在跳转界面时,没有左滑右滑进入界面的动画,显得很僵硬,所以咱们要给跳转过程中增加上动画。

增加默认动画:

nav_graph_main.xml文件中的Design模式下,点击连贯两个Fragment的线。而后你会发现在右侧会呈现一个Animations的面板,而后咱们点击enterAnim这些选项最右侧的椭圆点,而后就会弹出Pick a Resoure的面板,咱们能够在这里抉择须要的动画,这里咱们就设置nav_default_enter_anim。同理exitAnim咱们也设置一个动画,nav_default_exit_anim。而后运行代码你就发现一个突变的跳转动画。而后配置动画后会发现action多了动画相干的属性

<fragment
    android:id="@+id/firstFragment"
    android:name="com.taxze.jetpack.navigation.FirstFragment"
    android:label="fragment_first"
    tools:layout="@layout/fragment_first" >
    <action
        android:id="@+id/action_firstFragment_to_secondFragment2"
        app:destination="@id/secondFragment"
        app:enterAnim="@anim/nav_default_enter_anim"
        app:exitAnim="@anim/nav_default_exit_anim"
        />
</fragment>

  • enterAnim: 跳转时的指标页面动画
  • exitAnim: 跳转时的原页面动画
  • popEnterAnim: 回退时的指标页面动画
  • popExitAnim:回退时的原页面动画

自定义动画

💡 在真正的业务需要中是会有很多不同的跳转动画的,官网提供的默认动画是不够的,所以咱们要学会自定义动画。

⑴创立Animation资源文件

右键点击res目录,而后顺次抉择NewAndroid Resource File。此时零碎会显示 New Resource File对话框。File name输出你的文件夹名(这里设置为slide_from_left),Resource type抉择Animation,而后咱们就能够发下在res目录下多了一个anim目录,外面寄存着咱们自定义的动画。

⑵编写咱们的动画代码

这里举几个罕用的例子:

//左滑成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromXDelta="-100%"
        android:toXDelta="0%">
    </translate>
</set>
//右滑成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="300"
        android:fromXDelta="0%"
        android:toXDelta="100%">
    </translate>
</set>
//旋转成果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="1000"
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />
​
    <rotate
        android:duration="1000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />
</set>

罕用的属性:

属性 介绍
alpha 透明度设置成果
scale 大小缩放成果
rotate 旋转成果
translate 位移成果

罕用设置:

属性 介绍
android:duration 动画时长
fromXX 开始状态
toXX 完结状态

⑶应用自定义动画文件

应用自定义动画也是和应用默认动画是一样的。

旋转成果:

如何传递数据?

💡Navigation 反对您通过定义目的地参数将数据附加到导航操作。个别状况下,倡议传递大量数据。例如传递userId,而不是具体用户的信息。如果须要传递大量的数据,还是举荐应用ViewModel。

nav_graph_main.xml文件中的Design模式下。点击选中其中的Fragment。在右侧的Attributes 面板中,点击Arguments选项右侧的加号。增加须要的参数。增加参数后,在箭头 Action 上点击,会在左边的 Argument Default Values中显示这个userId变量,在xml中也能够看到

//伪代码,请勿间接cv
<fragment
   ... 
   >
   ...
    <argument
        android:name="userId"
        android:defaultValue="1"
        app:argType="integer" />
</fragment>

代码解决:

//默认将 箭头 Action 中设置的参数传递过来
it.findNavController().navigate(R.id.action_firstFragment_to_secondFragment2)

动静传递数据

①咱们能够应用Bundle在目的地之间传递参数

//伪代码,请勿间接cv
view.findViewById<Button>(R.id.firstButton).setOnClickListener {
    val bundle = Bundle()
    bundle.putString("userId", "1")
    val navController = it.findNavController()
    navController.navigate(R.id.action_firstFragment_to_secondFragment2, bundle)
}

②而后咱们就能够承受参数啦

在对应的Fragment:

val tv = view.findViewById<TextView>(R.id.textView)
tv.text = arguments?.getString("userId")

在Activity应用setGraph切换不同的Navigation

通常状况下,咱们不止一个navigation的文件,咱们须要依据业务状况去判断应用哪个,这里就能够用到咱们的setGraph去切换不同的Navigation了。

①把activity_mainfragment标签下的app:navGraph这个属性去除

<fragment
    android:id="@+id/nav_host_fragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:defaultNavHost="true"/>

②在代码中通过setGraph设置app:navGraph

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initNav(1)
    }
    private fun initNav(id: Int) {
        var controller = Navigation.findNavController(this@MainActivity, R.id.nav_host_fragment)
        if (id == 1) {
            //设置对应的app:navGraph
            controller.setGraph(R.navigation.first)
        }
        if (id == 2) {
            controller.setGraph(R.navigation.second)
        }
        this@MainActivity.finish()
    }
}

到此,咱们曾经讲完了Navigation大部分的应用状况,上面来解说几个重要的点,并通过一个案例来学习总结这篇文章吧。

NavController

💡 咱们在后面曾经讲了Navigation的应用,在解决Fragment的对应跳转事件时,咱们用到了findNavController这个办法,其实呢,这个就是Navigation的三局部中的NavController中的一个api。那么什么是NavController呢?它是负责操作Navigation框架下的Fragment的跳转与退出、动画、监听以后Fragment信息,当然这些是基本操作。因为除了在Fragment中调用,在理论状况中它也能够在Activity中调用。如果能灵便的应用它,它能够帮你实现任何模式的页面跳转,也能够应用TabLayout配合Navigation在主页进行分页设计。

如何获取NavController实例呢?

在后面的根底应用中咱们也用到了。

//伪代码,请勿间接cv
//activity:
//Activity.findNavController(viewId: Int)
findNavController(R.id.nav_host_fragment).navigateUp()
​
//Fragment:
//Fragment.findNavController()
//View.findNavController()
findNavController().navigate(R.id.action_thirdFragment_to_firstFragment)

Navigation罕用操作:

①popBackStack弹出Fragment

当初咱们从oneFragment跳转到secondFragment在到thirdFragment,而后咱们想从thirdFragment回到secondFragment那儿就能够应用popBackStack

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        .....
        btn.setOnClickListener{
            //弹出Fragment
            controller.popBackStack()
        }
}

②弹出到指定的Fragment

也是应用popBackStack,这个办法能够实现清空两头导航栈堆的需要

//xxxFragment弹出到指定的Fragment。
//第二个参数的布尔值如果为true则示意咱们参数一的Fragment一起弹出,意思就是如果是false就popBackStack到
//xxxFragment,如果是true,就在xxxFragment在popBackStack()一次
controller.popBackStack(xxxFragment,true)

③navigateUp() 向上导航

findNavController(R.id.nav_host_fragment).navigateUp()

navigateUp也是执行返回上一级Fragment的性能。和popBackStack性能一样。那么既然它存在必定是有它非凡的中央的。navigateUp向上返回的性能其实也是调用popBackStack的。 然而,navigateUp的源码里多了一层判断,判断这个Navigation是否是最初一个Fragment。应用popBackStack()如果以后的返回栈是空的就会报错,因为栈是空的了,navigateUp()则不会,还是停留在以后界面。

④增加导航监听

val listener: NavController.OnDestinationChangedListener =
                object : OnDestinationChangedListener() {
                    fun onDestinationChanged(
                        controller: NavController,
                        destination: NavDestination,
                        @Nullable arguments: Bundle?
                    ) {
                         Log.d(TAG, "onDestinationChanged: id = ${destination.getId()}")
                  }
          }
//增加监听
controller.addOnDestinationChangedListener(listener)
//移除监听
controller.removeOnDestinationChangedListener(listener)

⑤获取以后导航目的地

应用getCurrentDestination能够获取以后导航的目的地

//获取
val destination = controller.getCurrentDestination()
Log.d(TAG, "onCreate: NavigatorName = ${destination.getNavigatorName()}")
Log.d(TAG, "onCreate: id = ${destination.getId()}")
Log.d(TAG, "onCreate: Parent = ${destination.getParent()}")

⑥判断以后页面显示的Fragment是不是指标Fragment

//可间接cv
fun <F : Fragment> isActiveFragment(fragmentClass: Class<F>): Boolean {
    val navHostFragment = this.supportFragmentManager.fragments.first() as NavHostFragment
    navHostFragment.childFragmentManager.fragments.forEach {
        if (fragmentClass.isAssignableFrom(it.javaClass)) {
            return true
        }
    }
    return false
}

应用 Safe Args 确保类型平安

💡 通过下面的NavController咱们就能够实现fragment之间的跳转,然而Google倡议应用 Safe Args Gradle 插件实现。这个插件能够生成简略的对象和构建器类,这些类就能够在目的地之间进行平安的导航和参数的传递啦。

那么,该如何应用 Safe Args呢。

①在我的项目最里面的build.gradle中退出

//将其放在plugins{}之前
buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.4.2"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

②在appmodule下的build.gradle退出

如需生成实用于 Java 模块或JavaKotlin混合模块的Java语言代码

apply plugin: "androidx.navigation.safeargs"

如需生成实用于 Kotlin独有的模块的Kotlin代码,请增加以下行:

apply plugin: "androidx.navigation.safeargs.kotlin"

💡 要应用Safe Args,必须在gradle.properties这个文件中退出

android.useAndroidX=true
android.enableJetifier=true

为了防止生成的类名和办法名过于简单,须要对导航图进行调整,批改了action的id,因为主动生成的id太长了,会导致插件生成的类名和办法名也很长。

//伪代码,请勿间接cv
<fragment
    android:id="@+id/blankFragment"
    android:name="com.taxze.jetpack.navigation.BlankFragment"
    android:label="fragment_blank"
    tools:layout="@layout/fragment_blank" >
    <action
        android:id="@+id/toSecond"
            批改此处id
        app:destination="@id/blankFragment2" />
</fragment>

而后就会为咱们生成BlankFragmentBlankFragment2的类啦,而后就能够和下面一样应用,传递参数啦。

var action = BlankFragment.actionJump("111")

也能够应用set办法对对应的参数进行赋值

action.setParam("222")

通过Navigation模拟WeChat底部跳转

💡通过Navigation实现开发中超级罕用的底部跳转性能

话不多说,先上效果图:

①右键点击res目录,而后顺次抉择NewAndroid Resource File。此时零碎会显示 New Resource File对话框。File name输出你的文件夹名(这里设置为menu),Resource type抉择Menu,而后咱们就能够发下在res目录下多了一个menu目录,外面寄存着咱们底部跳转的item

②进入menu.xmlDesign

填入四个Item,并别离设置idtitleicon


③创立四个Fragment,并在Navigation中建设链接

Fragment的布局非常简略,这里就放一个的代码。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HomeFragment">
​
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Home" />
</FrameLayout>
class HomeFragment : Fragment() {
​
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_home, container, false)
    }
​
}

nav_graph_main.xml建设连贯,留神这里每个Fragmentid要和menu.xml中的id一一对应


④在activity_main中应用BottomNavigationView建设底部跳转

这里在drawable下创立一个selector_menu_text_color.xml用于辨别以后的Item

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="#818181" android:state_checked="false"/>
    <item android:color="#45C01A" android:state_checked="true"/>
</selector>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
​
    <fragment
        android:id="@+id/nav_host_fragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph_main" />
​
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:itemIconTint="@drawable/selector_menu_text_color"
        app:labelVisibilityMode="labeled"
        app:itemTextColor="@drawable/selector_menu_text_color"
        app:menu="@menu/menu" />
</androidx.constraintlayout.widget.ConstraintLayout>

⑤在MainActivty中设置切换逻辑

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //去除标题栏
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
        setContentView(R.layout.activity_main)
​
        val navController: NavController = Navigation.findNavController(this, R.id.nav_host_fragment)
        val navigationView = findViewById<BottomNavigationView>(R.id.nav_view)
        NavigationUI.setupWithNavController(navigationView, navController)
    }
}

这样咱们就能够实现效果图中的成果啦,具体代码能够查看Git仓库😉

尾述

这篇文章曾经很具体的讲了Jetpack Navigation的大部分用法,不过在看完文章后,你仍需多多实际,置信你很快就能够把握Navigation啦😺 因为我自己能力也无限,文章有不对的中央欢送指出,有问题欢送在评论区留言探讨~

对于我

Hello,我是Taxze,如果您感觉文章对您有价值,心愿您能给我的文章点个❤️,也欢送关注我的博客。

如果您感觉文章还差了那么点货色,也请通过关注督促我写出更好的文章——万一哪天我提高了呢?😝

根底系列:

2022 · 让我带你Jetpack架构组件从入门到精通 — Lifecycle

学会应用LiveData和ViewModel,我置信会让你在写业务时变得轻松🌞

当你真的学会DataBinding后,你会发现“这玩意真香”!

Navigation — 这么好用的跳转治理框架你确定不来看看?(本文🌟)

以下局部还在码字,连忙点个珍藏吧🔥

2022 · 让我带你Jetpack架构组件从入门到精通 — Room

2022 · 让我带你Jetpack架构组件从入门到精通 — Paging3

2022 · 让我带你Jetpack架构组件从入门到精通 — WorkManager

2022 · 让我带你Jetpack架构组件从入门到精通 — ViewPager2

2022 · 让我带你Jetpack架构组件从入门到精通 — 登录注册页面实战(MVVM)

进阶系列:

协程 + Retrofit网络申请状态封装

Room 缓存封装

…..

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理