Android Jetpack Navigation组件使用,跳转,传参,action,回退,动态加载等

目录

一,简介

二,使用条件

三,主要组成

四,主要功能

五,使用

1,创建Navigation Graph导航图

3,编辑导航图,将目的地添加到导航图

4,连接目的地

5,将NavHostFragment添加到Activity中

6,跳转

7,全局的action

8,数据传递

9,回退

10,动态加载


一,简介

Navigation是Jetpack组件库的一部分,于2018年推出;主要用于Fragment的管理,及之间的跳转等,使单Activity架构更简单;

二,使用条件

1,AndroidStudio版本需3.2及以上版本

2,module下的build.gradle添加依赖,根据自己项目的语言选择性添加依赖;

dependencies {
  def nav_version = "2.3.0"

  // Java language implementation
  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"
}

关于依赖配置问题可以查看官网资料:https://developer.android.com/jetpack/androidx/releases/navigation

官网文档地址:https://developer.android.com/guide/navigation

本文使用的AndroidStudio版本号是4.0.1;

三,主要组成

  • Navigation Graph :导航图是一个xml资源;创建于res/navigation/下;
  • NavHostFragment:类似于一个容器,使Navigation Graph添加其中;
  • NavController:处理Fragment间的跳转(Kotlin / Java对象);

四,主要功能

  1. 视觉导航图
  2. 按目的地和动作导航
  3. 过渡动画
  4. 菜单导航,底部导航和菜单抽屉导航
  5. 类型安全参数传递
  6. 深层连结

目的地可以理解为Fragment或者Activity还可以是另一个导航图;有的时候也叫目标;

五,使用

1,创建Navigation Graph导航图

右键项目new —>Android Resource File,填写File name名字自定义这里就叫navi_graph,Resource type选择Navigation,Directory name使用navigation;

注意:将导航图添加到项目中时,如果尚未将导航依赖项添加到应用程序的build.gradle文件中,则Android Studio会显示提示并为您添加依赖项。

<?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/navi_graph">

</navigation>
  • <navigation> 是每个导航图的根节点。
  • <navigation>包含一个或多个以<activity>或表示的目的地<fragment>。
  • app:startDestination 是一个属性,它指定用户首次打开应用程序时默认启动的目的地。 

在导航编辑器中,可以直观地编辑导航图也可也直接编辑XML。

主要分不分:

  1.  “目标”面板:列出导航主机和“ 图形编辑器”中当前存在的所有目标。
  2. 图形编辑器:包含导航图的可视表示。可以在“ 设计”视图和“ 文本”视图中的基础XML表示形式之间切换。
  3. 属性:在导航图中显示当前选定项目的属性。

3,编辑导航图,将目的地添加到导航图

进入导航图navi_graph.xml编辑模式下,点击右上角的Split,一个导航图是包含所有的目的地和Action的XML资源文件;

第一种方式

点击进入New Destination,选择Create new Destination 以这个为例;创建一个Fragment,名字叫FirstFragment

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/navi_graph"
    app:startDestination="@id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.example.navigationdemo.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" />
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.example.navigationdemo.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" />
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.example.navigationdemo.ThirdFragment"
        android:label="fragment_third"
        tools:layout="@layout/fragment_third" />

</navigation>

多创建几个Fragment,后面讲跳转会用到;

注意:app:startDestination="@id/firstFragment"类似于MainActivity;fragment标签的属性可以通过单击一个目标以将其选中,然后在“ 属性”面板中修改和设置,也可直接编辑XML;

第二种方式

如果之前新建好了Fragment,这里可以点击进入New Destination找到之前新建好的Fragment引入即可,比如我之前已经有了一个TestFragment其布局为fragment_test;这里显示的是其布局文件名;

4,连接目的地

上面有提到一个导航图还包含Action标签,这个就是目的地间逻辑连接,它可以在navigation标签下,也可以在fragment标签下;action标签还有destination 属性是表示目的地,要跳转到哪里的;还有个id属性,它和其他控件id含义一样,对比理解就好;在XML中通过action标签、属性destination,id就可实现目标的连接;

或者通过导航编辑器连接两个目的地:

在“ Design”选项卡中,将鼠标悬停在您要用户导航的目标的右侧。在目标的右侧上方将出现一个圆圈

点击圆圈并拖动鼠标,拖到想要连接的另一个目的地,两个目的地之间的结果线代表一个动作;

单击文本选项卡切换到XML视图。现在将action添加到id为firstFragment源目标。该action具有一个id和一个destination属性,destination属性值包含的是下一个目的地的id,如以下示例所示:

<?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/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.ang.navigationtest.FirstFragment"
        android:label="fragment_first"
        tools:layout="@layout/fragment_first" >
        <action
            android:id="@+id/action_firstFragment_to_secendFragment"
            app:destination="@id/secendFragment" />
    </fragment>
    <fragment
        android:id="@+id/secendFragment"
        android:name="com.ang.navigationtest.SecendFragment"
        android:label="fragment_secend"
        tools:layout="@layout/fragment_secend" />
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.ang.navigationtest.ThirdFragment"
        android:label="fragment_third"
        tools:layout="@layout/fragment_third" />
</navigation>

 请注意,要实际导航到目的地,仍然需要编写代码来执行导航。这个后面将跳转在具体说;

5,将NavHostFragment添加到Activity中

也是有两种方式:

第一种方式

在MainActivity的activity_main.xml布局中编写;具体代码如下,name是固定的不能修改,navGraph属性值是

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/nav_host_fragments"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/navi_graph"/>

  </androidx.constraintlayout.widget.ConstraintLayout>

app:defaultNavHost="true":让 Navigation 容器处理返回事件,在 Navigation 容器中如果有页面的跳转,点击返回按钮会先处理 容器中 Fragment 页面间的返回,处理完容器中的页面,再处理 Activity 页面的返回。如果值为 false 则直接处理 Activity 页面的返回。这里你能会发现,刚才navigation graph中爆红,现在消失了;

第二种方式:

如果你的Activity布局使用的约束布局的话,在布局的视图Split下,Containers中拖拽一个NavHostFragment,然后选择自己的导航图文件即可;别忘了设置约束哦

6,跳转

要实现目的地间的跳转,是通过NavController

获取NavController主要有三种方式

NavHostFragment.findNavController(Fragment)
Navigation.findNavController(Activity, @IdRes int viewId)
Navigation.findNavController(View

好像这种也是可以的

FragmentManager supportFragmentManager = getActivity().getSupportFragmentManager();
NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.fragment);
NavController navController = navHostFragment.getNavController();

然后通过NavController 的navigate方法实现跳转;这里的resId可以是导航图中的目的地fragment的id,也可以是源目的地的action的id;

//navigate方法
public void navigate(@IdRes int resId) {
     navigate(resId, null);
}

也可以通过如下方式实现跳转

view.findViewById(R.id.btn_to_secend).setOnClickListener( Navigation.createNavigateOnClickListener(R.id.secendFragment, null));

7,全局的action

上面有提到在navigation标签下也可以添加action,这个就是全局的action,可以解决多个源目的地跳转到同一个目的地,不用每个源目的地中都写同一个action了,准确的说应该是destination属性;

8,数据传递

NavController 的navigate跳转方法还有个重载方法,有个Bundle参数,所以可通Bundle实现目的地间的数据传递;

public void navigate(@IdRes int resId, @Nullable Bundle args) {
     navigate(resId, args, null);
}

9,回退

既然NavController可以实现跳转,那么相似的功能回退呢,当然也可以实现,NavController有 navigateUp() 和 popBackStack() 两个方法可以返回上一级;

10,动态加载

可以在Fragment或者Activity中动态加载Navigation:

FragmentManager supportFragmentManager = getSupportFragmentManager();
NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.fragment);
NavController navController = navHostFragment.getNavController();
navController.setGraph(R.navigation.nav_graph);
NavHostFragment也是一个Fragment;可以当作一个Fragment使用;

猜你喜欢

转载自blog.csdn.net/ezconn/article/details/108671409