Jetpack 之 Navigation 初探

简介

Google 2018 I/O大会上,Google正式推出了Android/Jetpack,其中隆重推出了一个新的架构组件:Navigationphp

Google 官方介绍:java

做为构建您的应用内界面的框架,重点是让单 Activity 应用成为首选架构。利用 Navigation 组件对 Fragment 的原生支持,您能够得到架构组件的全部好处(例如生命周期和 ViewModel),同时让此组件为您处理 FragmentTransaction 的复杂性。此外,Navigation组件还可让您声明咱们为您处理的转场。它能够自动构建正确的“向上”和“返回”行为,包含对深层连接的完整支持,并提供了帮助程序,用于将导航关联到合适的 UI 小部件,例如抽屉式导航栏和底部导航。android

集成环境

Android Studio 3.2+ 下载地址:developer.android.com/studio/prev…git

添加依赖

Step-1:

repositories 添加 Google 仓库和 classpathgithub

buildscript {
    repositories {
        google()
    }
    dependencies {
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha01"
    }
}
复制代码

Step-2:

添加 Navigation 库的依赖架构

dependencies {
    def nav_version = "1.0.0-alpha01"

    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin

    // optional - Test helpers
    androidTestImplementation "android.arch.navigation:navigation-testing:$nav_version" // use -ktx for Kotlin
}
复制代码

新建 Navigation

  • 新建 Android 项目
  • res 目录右键 New->New Resource File,弹出 New Resource File 的对话框。
  • 填写 File Name 如:nav_graph,Resource type 选择 Navigation,点击OK(Android Studio 3.3新建项目会自动生成该目录)。

以上操做会在 res 下生成一个 navigation 目录,目录下有刚才新建的 nav_graph.xml 文件,打开该文件,内容是一个 navigation 的空节点。和布局文件相似,AndroidStudio 界面上有。app

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android">

</navigation>
复制代码

使用 Navigation

Step-1:

新建两个 Fragment:FragmentA、FragmentB 对应布局为 fragment_a.xml、fragment_b.xml框架

Step-2:

打开 nav_graph.xml,底部选择 Design 选项卡,点击 New Destination (左上角 + ) 按钮,在弹窗中选择 fragment_a.xmlfragment_b.xml,或选择 Create blank destination 新建Fragment.以后选显示以下界面:ide

image

此时 nav_graph.xml 内容以下,点击 Text 切换布局

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragmentA">

    <fragment android:id="@+id/fragmentA" android:name="com.halove.jetpackdmeo.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a" >
    </fragment>
    <fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" />
</navigation>
复制代码

Step-3:

在 Activity 布局里添加 NavHostFragment (关于 NavHostFragment 能够看这篇博客,解释的很清楚 blog.csdn.net/mq2553299/a…)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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/my_nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/nav_graph" />

</android.support.constraint.ConstraintLayout>
复制代码

app:defaultNavHost="true" 是拦截返回键,即将返回托管给NavHostFragment处理。不然返回直接退出当前 Activity 。app:navGraph="@navigation/nav_graph"将 NavHostFragment 跟咱们刚才建立的 navigation 关联。 而后从新打开 nav_graph.xml 会发如今 HOST 下面就会显示咱们关联的 activity:

image

Step-4:

添加导航链接

左键按住 fragment 右侧中间的圆圈而后拖动到要导航的 fragment 而后松手

image

切换到 Text 模式下,发如今 fragment 标签里添加了一个 action 节点,action 添加了一个 id 和 destination ,destination 就是咱们要导航到的 fragment。

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragmentA">

    <fragment android:id="@+id/fragmentA" android:name="com.halove.jetpackdmeo.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a" >
        <action android:id="@+id/action_fragmentA_to_fragmentB" app:destination="@id/fragmentB" />
    </fragment>
    <fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" />
</navigation>
复制代码

Activity 中不须要作任何操做,只须要设置布局便可:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
    }
}
复制代码

在 FragmentA 中布局中添加一个 Button ,点击跳转到 FragmentB :

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
   
        to_fragmentb_btn.setOnClickListener {
            Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB)
        }
        to_fragmentb_btn.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_fragmentA_to_fragmentB))
 }
复制代码

使用很简单,调用 Navigation 的 findNavController 方法找到 NavController , findNavController 还有其余参数的方法你们能够本身试试,而后调用 navigate 方法,参数就是 nav_graph.xml 里 actionid 。或者直接使用 createNavigateOnClickListener.

按返回键会回退到上一个 Fragment ,也能够调用 NavController 的 popBackStack 进行回退

页面传参

1 .代码传参

navigate 有好几个方法,如图所示:

image

可使用Bundle传参

val bundle = Bundle()
 bundle.putString("param", "I AM FROM FRAGMENT-A")
 Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentC,bundle)
复制代码

2. xml 文件传参

在 navigation 的xml的 fragment 的 action 里添加 argument 标签,而后使用生成的对应的 Agrs 或者 Directions 来传递参数,须要在 build.gradle 中添加 apply plugin: 'androidx.navigation.safeargs'

<fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" >
    <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
</fragment>
复制代码

传参:

FragmentBArgs 和 FragmentADirections 都是自动生成的,FragmentBArgs 是根据fragment 节点下的 argument 节点生成的,FragmentADirections 是根据 action 生成的

//使用FragmentBArgs
val bundle = FragmentBArgs.Builder().setText("Hello World").build().toBundle()
Navigation.findNavController(it).navigate(R.id.action_fragmentA_to_fragmentB, bundle)

//使用FragmentADirections
val direction = FragmentADirections.action_fragmentA_to_fragmentB().setText("Hello World")
Navigation.findNavController(it).navigate(direction)
复制代码

3. 参数接收

val text = FragmentBArgs.fromBundle("key").text
//或
val text =  arguments!!["key"].toString()
复制代码

转场动画

转场动画能够直接在 action 里面使用动画文件:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" app:startDestination="@id/fragmentA">

    <fragment android:id="@+id/fragmentA" android:name="com.halove.jetpackdmeo.FragmentA" android:label="fragment_a" tools:layout="@layout/fragment_a" >
        <action android:id="@+id/action_fragmentA_to_fragmentB" app:destination="@id/fragmentB" app:enterAnim="@anim/slide_in_right" app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right"/>
    </fragment>
    <fragment android:id="@+id/fragmentB" android:name="com.halove.jetpackdmeo.FragmentB" android:label="fragment_b" tools:layout="@layout/fragment_b" >
        <argument android:name="text" android:defaultValue="Hello" app:type="string"/>
    </fragment>
</navigation>
复制代码

Demo

附上使用小 Demo

地址:github.com/wanglejun/N…

相关文章
相关标签/搜索