JetPack之Navigation入门


一、简介

JetPack Navigation 是 Android JetPack 组件库中的一个组件,用于简化 Android 应用中的导航和页面间的跳转。它提供了一种统一的方式来管理应用中的导航结构,帮助开发者更容易地实现页面间的跳转和管理。简单来说,Navigation是管理Fragment之间导航的组件库,特别在实现单个Activity多个Fragment的管理模式中非常灵活。

1.1 核心概念和组件

概念描述
Navigation Graph(导航图)导航图是一个 XML 文件,用于定义应用中的导航结构,包含了应用中所有页面之间的导航关系。通过导航图,可以清晰地看到应用的整体导航结构,方便管理和维护。
NavHostFragment(导航宿主Fragment)NavHostFragment 是一个特殊的 Fragment,用于承载应用中的所有 Fragment,并负责管理这些 Fragment 之间的导航。每个 NavHostFragment 都会关联一个导航图,用于指定该 NavHostFragment 中的页面导航规则。
NavController(导航控制器)NavController 是用于管理页面导航的控制器,负责处理页面之间的跳转、返回栈管理、深层链接等操作。可以通过 NavController 来执行页面间的跳转操作。
Navigation Component(导航组件)Navigation Component 是 JetPack Navigation 的核心组件,提供了一系列 API 来简化页面导航的实现。通过 Navigation Component,可以更容易地实现页面间的跳转、传递参数、处理返回栈等操作。

1.2 优点

  • 统一的导航结构:通过导航图可以清晰地定义应用的导航结构,使得整个应用的导航管理更加清晰和统一。
  • 类型安全的导航:通过使用安全参数和类型安全的操作符来执行页面跳转,避免了传统 Intent 跳转中的字符串传参等问题,提高了代码的可维护性和安全性。
  • 返回栈管理:Navigation Component 提供了一套完整的返回栈管理机制,可以方便地管理页面返回栈,实现页面的正确返回和跳转。
  • 深层链接支持:支持通过深层链接直接跳转到应用的指定页面,方便实现推送通知等功能。

二、使用

导航图(navGraph):这是包含所有导航相关信息的 XML 资源,这些信息包括应用内所有内容区域个体(称为目标,一般都是 Fragment),以及用户可以通过应用跳转的可能路径。
导航宿主(NavHost):这是用来显示导航图中声明的目标的一个空白容器。导航组件包含一个默认的 NavHost 实现 (NavHostFragment),可用于显示 Fragment 目标。
导航控制器(NavController):在 NavHost 中管理应用导航的目标,当用户在应用中进行操作时,导航控制器会控制目标的切换。

接下来的示例中,用上述三个核心组件去实现一个简易的Navigation导航demo,
Activity持有NavHostFragment(导航宿主),导航宿主布局指向navGraph(导航图),导航图加载和规划了Fragment的导航方向,使用导航控制器完成跳转。
示意图如下:
在这里插入图片描述

2.1 导入依赖

dependencies {
  def nav_version = "2.7.7"

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

  // Feature module Support
  implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

  // Testing Navigation
  androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

  // Jetpack Compose Integration
  implementation "androidx.navigation:navigation-compose:$nav_version"
}

2.2 导航图Navigation Graph

2.2.1 在导航图中放入三个Fragment

Page1Fragment :返回布局、注册点击事件

public class Page1Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//        return super.onCreateView(inflater, container, savedInstanceState);
        return inflater.inflate(R.layout.page1fragment, container, false);

    }

    //点击事件,跳转到第二个Fragment
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btn = view.findViewById(R.id.Page1Button);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(view).navigate(R.id.action_page2);
            }
        });
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Page1Fragment"
        android:textColor="@color/blue" />

    <Button
        android:id="@+id/Page1Button"
        android:layout_width="120dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:background="@color/pink"
        android:text="跳转Page2Fragment"
        android:textColor="@color/blue" />

</LinearLayout>

Page2Fragment :返回布局、注册点击事件

public class Page2Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        return inflater.inflate(R.layout.page2fragment, container, false);
    }

    //点击事件,前进和后退点击事件注册
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btnforward = view.findViewById(R.id.Page2forward);
        btnforward.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(view).navigate(R.id.action_page3);
//                Navigation.findNavController(view).navigateUp();
            }
        });

        Button btnbackward = view.findViewById(R.id.Page2backward);
        btnbackward.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(view).navigate(R.id.action_page1);
            }
        });
        
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/violet"
    android:orientation="vertical">


    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Page2Fragment"
        android:textColor="@color/blue" />


    <Button
        android:id="@+id/Page2forward"
        android:layout_width="120dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:background="@color/pink"
        android:text="跳转Page3Fragment"
        android:textColor="@color/blue" />

    <Button
        android:id="@+id/Page2backward"
        android:layout_width="120dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:background="@color/pink"
        android:text="返回Page1Fragment"
        android:textColor="@color/blue" />
</LinearLayout>

Page3Fragment :返回布局、注册点击事件

public class Page3Fragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.page3fragment, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btnforward = view.findViewById(R.id.Page3Back);
        btnforward.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Navigation.findNavController(view).navigate(R.id.action_page3_2);
            }
        });

    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bisque"
    android:orientation="vertical">


    <TextView
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Page3Fragment"
        android:textColor="@color/blue" />


    <Button
        android:id="@+id/Page3Back"
        android:layout_width="120dp"
        android:layout_height="50dp"
        android:layout_gravity="center"
        android:layout_marginTop="100dp"
        android:background="@color/pink"
        android:text="返回到Page2Fragment"
        android:textColor="@color/blue" />

</LinearLayout>

2.2.2 创建导航图

资源文件夹中创建Navigation根布局
在这里插入图片描述
在这里插入图片描述
选择+号,添加目的地
在这里插入图片描述
从中可以选择本地所有的Fragment
在这里插入图片描述

依次添加好上面编写的三个Fragment,可以看到,

<?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_main"
    app:startDestination="@id/page1Fragment">

    <fragment
        android:id="@+id/page1Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page1Fragment"
        android:label="Page1Fragment" />
    <fragment
        android:id="@+id/page2Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page2Fragment"
        android:label="Page2Fragment" />
    <fragment
        android:id="@+id/page3Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page3Fragment"
        android:label="Page3Fragment" />

</navigation>

连接Fragment的跳转顺序,这样下来,Fragmen1可以跳转到Fragmen2,Fragmen2可以跳转到3…
在这里插入图片描述
布局代码会跟着发生变化:

<?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/page1Fragment">
    <!--    默认启动page1Fragment-->

    <!--    第一个Fragment-->
    <fragment
        android:id="@+id/page1Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page1Fragment"
        android:label="Page1Fragment">
        <action
            android:id="@+id/action_page2"
            app:destination="@id/page2Fragment" />
    </fragment>

    <!--    第二个Fragment-->
    <fragment
        android:id="@+id/page2Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page2Fragment"
        android:label="Page2Fragment">
        <action
            android:id="@+id/action_page3"
            app:destination="@id/page3Fragment" />
        <action
            android:id="@+id/action_page1"
            app:destination="@id/page1Fragment" />
    </fragment>

    <!--    第三个Fragment-->
    <fragment
        android:id="@+id/page3Fragment"
        android:name="com.henry.jetPackTest.navigationTest.Page3Fragment"
        android:label="Page3Fragment">
        <action
            android:id="@+id/action_page3_2"
            app:destination="@id/page2Fragment" />
    </fragment>

</navigation>

2.3 导航宿主、导航控制器

将导航宿主注册在Activity的布局文件中,使用BottomNavigationView模拟导航控制器
android:name="androidx.navigation.fragment.NavHostFragment"必不可少

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <fragment
        android:id="@+id/my_nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="9"
        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="wrap_content"
        app:itemTextColor="@color/pink"
        app:menu="@menu/menu_fragment" />

</LinearLayout>

菜单布局

<?xml version="1.0" encoding="utf-8"?>
<menu 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">
    <item
        android:id="@+id/page1Fragment"
        android:icon="@drawable/setting"
        android:title="第一页"
        app:showAsAction="withText" />
    <item
        android:id="@+id/page2Fragment"
        android:icon="@drawable/setting"
        android:title="第二页"
        app:showAsAction="withText" />
    <item
        android:id="@+id/page3Fragment"
        android:icon="@drawable/setting"
        android:title="第三页"
        app:showAsAction="withText" />
</menu>

2.4 Activity

public class NavigationTestActivity extends AppCompatActivity {
    BottomNavigationView bottomNavigationView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.navigationtest);
        //通过 findViewById 方法找到布局文件中 ID 为 nav_view 的 BottomNavigationView 控件,并将其赋值给 bottomNavigationView 变量。
        bottomNavigationView = findViewById(R.id.nav_view);
        //NavHostFragment 是用于承载导航图的容器。
        NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.my_nav_host_fragment);
        //获取与 NavHostFragment 关联的 NavController,用于管理应用程序的导航操作。
        NavController navController = navHostFragment.getNavController();
        //与 navController 关联起来,使得底部导航栏中的菜单项可以与导航控制器进行交互,实现页面之间的导航。
        NavigationUI.setupWithNavController(bottomNavigationView, navController);

    }
}

实现效果:

在这里插入图片描述

三、进阶使用

上述demo仅仅设置目标页,其他功能如设置动画、页面间参数传递、fragment回退栈管理、深度链接等参考其他博客:

参考链接:
谷歌官方:Navigation
Android导航组件Navigation从入门到精通
安卓navigation系列——入门篇

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值