我们了解了Navigation之后,就不得不提Navigation Editor。我们可以通过Android Studio的 Navigation Editor去编辑和浏览我们的Navigation graph(导航图)
请注意这里必须要求我们的的Android Studio版本在3.3或者以上版本
目前也有很多文章介绍Navigation以及Navigation Editor但是更多的是介绍Android Studio3.3之前版本的,本篇文章着重介绍的是Android Studio3.3及以上版本,有很多不同之处。如需应用以下内容请先升级Android Studio至3.3或者以上版本。
在Module下面的build.gradle当中
dependencies {
def nav_version = "1.0.0"
implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin
}
导航是发生在应用的目标示图之间——用户可以导航到应用当中的任何的位置。将这些目标视图通过操作来连接起来。
导航图是包括所有的目标视图和操作的一个资源文件,这个导航图标代表了我们应用的所有的导航路径图。
在Android Studio的主界面,在res目录的文件夹下面,选择New > Android Resource File然后我们就可以看到 New Resource File对话框。如下图:
如果我们是第一次创建导航图,Android Studio会在res文件夹下面创建一个navigation 的资源文件目录,这个目录当中就包含了我们刚才创建的资源文件。如图:
点击打开刚才创建的Navigation的xml文件,然后选择Design。
我们可以看到Navigation Editor控制面板自左向右有三部分如图:
控制面板分成了三部分分别是:
点击Text我们可以看到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"
android:id="@+id/nav_graph">
</navigation>
这里的</navigation>
是导航图的根元素,当我们要在图标当中添加目标视图和连接动作的时候,我们可以使用<destination>
和<action>
元素作为子元素。
一个主导航必须由NavHost派生而来,导航组件默认通过NavHost来实现,NavHostFragment来处理目标fragment直接的切换。
在我们应用程序的main activity当中添加NavHostFragment
这里的添加有两种方式
1.复制下面代码到xml的代码文件当中
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/nav_graph"
app:defaultNavHost="true"
/>
2.在design下面控制面板选择
位置如图:
然后我们直接拖NavHostFragment 的视图到我们的activity文件当中
这里总共有三种不同的方式可以在我们的导航视图当中添加目标视图
如果我们想把已经存在的目标视图想要添加在导航图当中,我们只需要点击New Destination然后找到已经存在目标视图,选择即可。
如图:
填写完信息之后,我们就可以看到界面上出现了我们刚才创建的目标视图
如图:
目标视图我们已经创建完成了,接下来我们就开始连接各个目标视图了。当然,我们连接目标视图就是通过Navigation Editor来完成。
然后拖拽鼠标,然后连接到了我们想要链接的目标视图。之后我们就可以看到一个线的箭头如图:
这个就表示我们把两个目标视图连接了。
<?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/oneFragment">
<fragment android:id="@+id/oneFragment" android:name="demo.rlv.cehome.com.navigationcomponents.OneFragment"
android:label="fragment_one" tools:layout="@layout/fragment_one">
<action android:id="@+id/action_oneFragment_to_twoFragment" app:destination="@id/twoFragment"/>
</fragment>
<fragment android:id="@+id/twoFragment" android:name="demo.rlv.cehome.com.navigationcomponents.TwoFragment"
android:label="fragment_two" tools:layout="@layout/fragment_two"/>
</navigation>
导航到目标视图,我们需要用到NavController,它是用于管理NavHost中的应用程序导航的对象。 每个NavHost都有自己的相应NavController。
NavController有以下几种获取方式:
对于Java来说:
对于Kotlin来说:
下面我们就看一下在我们要实现的效果:
下面我们看一下实现代码,在OneFragment当中
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
view?.findViewById<Button>(R.id.button_one)?.setOnClickListener {
view?.let { Navigation.findNavController(it).navigate(R.id.twoFragment)
}
}
}
只需要添加就可以实现跳转功能,是不是很方便?
Navigation.findNavController(it).navigate(R.id.twoFragment)
对于Button控件来说,还有另一种实现跳转的方法
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
// view?.findViewById<Button>(R.id.button_one)?.setOnClickListener {
// view?.let { Navigation.findNavController(it).navigate(R.id.twoFragment)
// }
// }
button_one.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.twoFragment, null))
}
两种跳转分别是传入nav_graph.xml当中的action id和resource id。
两种方法都可以实现跳转,但是我更建议用第一种,因为第一种可以配合着过渡的动画使用。
我们常见的一种逻辑如下:
有三个目标视图分别是A、B、C,有A到B,B到C,然后C到A。
可以看到当我们倒C之后,后台堆栈当中包括A、B、C单个实例。当我们通过popUpTo A
回到A的时候,意味着我们从堆栈当中把B和C删除了。当我们使用app:popUpToInclusive =“true”
的时候,我们还会把A弹出堆栈并有效的清除它。如果我们没有使用app:popUpToInclusive =“true”
那么也意味着我们的堆栈当中包含两个A的实例。
实现代码如下:
<action
android:id="@+id/action_c_to_a"
app:destination="@id/a"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"/>
当我尝试写这篇文章,并认真看过了官方文档,自己也实践之后发现Navigation以及Navigation Editor真的非常实用!在代码当中,我们不用写很多的Activity。写一个Activity嵌套多个Fragment就可以完成,当然这也是谷歌一直推崇的一种方式。那么不同的Fragment之间的跳转,可能就是摆在我们面前的一大难题,经常会有这样会那样的问题,同时逻辑不是很清晰并且需要大量的代码用来实现。但是有了Navigation和Navigation Editor之后就有效的解决了这一问题!
https://github.com/yang0range/NavigationComponent