学习记录(3)- Navigation

作者: 九馆 | 来源:发表于2020-10-30 00:21 被阅读0次

    前言

    学习记录系列是通过阅读学习《Android Jetpack应用指南》对书中内容学习记录的Blog,《Android Jetpack应用指南》京东天猫有售,本文是学习记录的第三篇。

    定义

    Navigation 是一个可简化 Android 导航的库和插件,用于构建和组织应用内界面,处理深层链接以及在屏幕之间导航。

    更确切的来说,Navigation 是用来在单个 Activity 嵌套多个 Fragment 的UI架构模式中管理 Fragment 的切换,并且可以通过可视化的方式,看见App的交互流程。旨在方便管理页面(页面包含 Fragment 和 Activity,主要值Fragment )和 App bar(ActionBar、ToolBar、CollapsingToolbarLayout)

    优势

    1、可视化的页面导航图,类似于 Apple Xcode 中的 StoryBoard,便于我们理清页面间的关系。
    2、通过 destination 和 action 完成页面间的导航。
    3、方便添加页面切换动画。
    4、页面间类型安全的参数传递
    5、通过 NavigationUI 类,对菜单、底部导航、抽屉菜单导航进行统一的管理
    6、支持深层链接 DeepLink

    Navigation的主要元素

    1、Navigation Graph:这是一种新型的 XML 资源文件,其中包含应用程序所有的页面,以及页面间的关系
    2、NavHostFragment:这是一个特殊的 Fragment。你可以认为它是其他 Fragmeng 的“容器”,Navigation Graph 中的Fragment 正是通过 NavHostFragment 进行展示的。
    3、NavController:这是一个 Java/Kotlin 对象,用于在代码中完成 Navigation Graph 中具体的页面切换工作。

    请认真阅读下面这句话,更好的理解上述 3 种元素之间的关系

    当你想切换 Fragment 时,使用 NavController 对象,告诉它你想要去 Navigation Graph 中的 哪个 Fragment,NavController 会将你想去的 Fragment 展示在NavHostFragment 中。

    使用Navigation

    1.创建 Navigation Graph
    新建一个 Android 项目后,依次选中 res 文件夹 → New → Android Resource File,新建一个 Navigation Graph 文件。如图所示: image.png 需要注意的点:使用 Navigation 需要依赖于相关支持库,因此当你没有添加相关依赖库的时候,Android Studio可能会询问你,是否自动帮你添加相关依赖。如图所示: image.png

    也可以手动添加相关依赖库

    dependencies {
        // Navigation 相关依赖
        implementation 'androidx.navigation:navigation-fragment:2.3.1'
        implementation 'androidx.navigation:navigation-ui:2.3.1'
    }
    
    2.添加 NavHostFragment

    NavHostFragment 是一个特殊的Fragment,需要将其添加到 Activity 的布局文件中,作为其他 Fragment 的容器。

    <?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=".navigation.NavigationActivity">
    
        <fragment
            android:id="@+id/nav_host_fragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:name="androidx.navigation.fragment.NavHostFragment"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"/>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    告诉系统,这是一个特殊的Fragment
    android:name="androidx.navigation.fragment.NavHostFragment"
    
    表示该Fragment会自动处理系统返回键,即当用户按下手机的返回按钮时,系统能自动将当前所展示的Fragment退出
    app:defaultNavHost="true"
    
    用于设置该Fragment对应的导航图
    app:navGraph="@navigation/nav_graph"
    
    添加 NavHostFragment 之后,在回到导航图上。此时,在 Destinations 面板中可以看见我们刚才设置的 NavHostFragment。如图所示: image.png
    3.创建 destination
    1.点击加号按钮,"Create new destination" 按钮,创建一个 destination。如图所示: image.png 2.destination 是“目的地”的意思,代表着你想去的页面。它可以是 Fragment 或 Activity,但最常见的是 Fragment,因为 Navigation 组件的作用是方便开发者在一个 Activity 中管理多个 Fragment。在此,通过 destination 创建一个名为 MainFragment 的 Fragment image.png 3.面板中出现了一个 mainFragment,“Start”表示该 MainFragment 是起始 Fragment,即 NavHostFragment 容器首先展示的 Fragment。 image.png 4.查看nav_graph.xml布局文件内容,可以看到,在 navigation 标签下有一个 startDestination 属性,该属性指定起始 destination 为 mainFragment。
    <?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/mainFragment">
    
        <fragment
            android:id="@+id/mainFragment"
            android:name="com.jinxin.navigation.MainFragment"
            android:label="fragment_main"
            tools:layout="@layout/fragment_main" />
    </navigation>
    

    5.运行程序,可以看到一个空白的 Fragment, 即 destination 所指定的 mainFragment


    image.png
    4. 完成 Fragment 页面切换
    1.创建 SecondFragment,创建完成之后,在导航面板中单击 mainFragment,用鼠标选中其右侧的圆圈,并拖拽至右边 secondFragment,松开鼠标之后会出现一个从 mainFragment 指向 secondFragment 的箭头 image.png

    查看布局文件,可以看到多了一个 <action/> 标签,app:destination 属性表示它的目的地是 secondFragment

    <?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/mainFragment">
    
        <fragment
            android:id="@+id/mainFragment"
            android:name="com.jinxin.navigation.MainFragment"
            android:label="fragment_main"
            tools:layout="@layout/fragment_main" >
            
            <action
                android:id="@+id/action_mainFragment_to_secondFragment"
                app:destination="@id/secondFragment" />
            
        </fragment>
    
        <fragment
            android:id="@+id/secondFragment"
            android:name="com.jinxin.navigation.SecondFragment"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" />
        
    </navigation>
    
    5. 使用 NavController 完成导航

    在 MainFragment 的布局文件中添加两个Button,分别对应两种跳转页面的方式。

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_main, container, false);
    
            // 方法1
            view.findViewById(R.id.btn_to_second_fragment_1).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Navigation.findNavController(v).navigate(R.id.action_mainFragment_to_secondFragment);
                }
            });
    
            // 方法二
            view.findViewById(R.id.btn_to_second_fragment_2)
                    .setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_mainFragment_to_secondFragment));
            return view;
        }
    

    运行应用程序可以看到 Fragment 完成了切换,但切换没有动画效果,显示很生硬。

    6. 添加页面切换动画效果
    首先,在 res/anim 文件夹下加入常见的动画文件 image.png
    slide_in_left.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="-100%" android:toXDelta="0%"
            android:fromYDelta="0%" android:toYDelta="0%"
            android:duration="700"/>
    </set>
    
    slide_in_right.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="100%" android:toXDelta="0%"
            android:fromYDelta="0%" android:toYDelta="0%"
            android:duration="700"/>
    </set>
    
    slide_out_left.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="100%" android:toXDelta="0%"
            android:fromYDelta="0%" android:toYDelta="0%"
            android:duration="700"/>
    </set>
    
    slide_out_right.xml
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="100%" android:toXDelta="100%"
            android:fromYDelta="0%" android:toYDelta="0%"
            android:duration="700"/>
    </set>
    
    接着打开导航面板,选中箭头,并在右边 Animations 面板中为其设置动画文件 image.png

    查看布局文件,可以看到它在<action/>标签中自动添加了动画的相关代码。实际上,我们可以在布局文件中编写代码,Design 面板只是使用了可视化的方式以方便操作。

    <?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/mainFragment">
    
        <fragment
            android:id="@+id/mainFragment"
            android:name="com.jinxin.navigation.MainFragment"
            android:label="fragment_main"
            tools:layout="@layout/fragment_main" >
    
            <action
                android:id="@+id/action_mainFragment_to_secondFragment"
                app:destination="@id/secondFragment"
                app:popEnterAnim="@anim/slide_in_left"
                app:popExitAnim="@anim/slide_out_right"
                app:enterAnim="@anim/slide_in_right"
                app:exitAnim="@anim/slide_out_left"/>
    
        </fragment>
    
        <fragment
            android:id="@+id/secondFragment"
            android:name="com.jinxin.navigation.SecondFragment"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" />
    
    </navigation>
    

    使用safe args 插件传递参数

    1.常见的传递参数的方式

    Fragment 的切换经常需要伴随着参数的传递,为了配合 Navigation 组件在切换 Fragment 时传递参数,Android Studio 为开发者提供了 safe args 插件。在介绍 safe args 插件之前,Fragment 间最常见的传递参数和接收参数的方式
    MainFragment 传递参数:

     Bundle bundle = new Bundle();
     bundle.putString("user_name", "Michael");
     bundle.putInt("age", 30);
     Navigation.findNavController(v).navigate(R.id.action_mainFragment_to_secondFragment, bundle);
    

    SecondFragment 接收参数:

    TextView tvUserName = view.findViewById(R.id.tv_user_name);
    TextView tvAge = view.findViewById(R.id.tv_age);
    Bundle arguments = getArguments();
    if (arguments != null) {
        String userName = arguments.getString("user_name");
        int age = arguments.getInt("age");
    
        tvUserName.setText(userName);
        tvAge.setText(String.valueOf(age));
    }
    
    2.使用 safe args 传递参数

    首先,需要安装 safe args 插件。在 Project 的 build.gradle 文件中添加 safe args 插件。

        dependencies {
            classpath 'com.android.tools.build:gradle:4.0.2'
    
            // Navigation 使用Safe Arg 插件传递参数
            classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.3.1'
        }
    

    接着,需要引用该插件。在 app 的 build.gradle 文件中添加对 safe args 的依赖

    apply plugin: 'androidx.navigation.safeargs'
    

    在 nav_graph.xml 布局文件中添加 <argument/> 标签。可以在布局文件中编写代码,也可以通过 Design 面板进行添加,因为是 secondFragment 接收参数展示,所以在 secondFragment 中添加参数

        <fragment
            android:id="@+id/secondFragment"
            android:name="com.jinxin.navigation.SecondFragment"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" >
    
            <!-- 添加参数 -->
            <argument
                android:name="userName"
                app:argType="string"
                android:defaultValue='"unknown'/>
    
            <!-- 添加参数 -->
            <argument
                android:name="age"
                app:argType="integer"
                android:defaultValue="0"/>
    
        </fragment>
    
    添加 <argument/>标签之后,build一下工程,便可以在 app/generatedJava 目录下看到 safe args 插件生产的代码文件了,这些代码文件中包含了参数所对应的 Getter 和 Setter 方法。 image.png

    最后,在Fragment 中利用所生产的代码文件,在 Fragment 之间进行参数传递。

    使用 safe args 传递参数 
    Bundle bundle = new SecondFragmentArgs.Builder()
                            .setUserName("Michael")
                            .setAge(30)
                            .build().toBundle();
    Navigation.findNavController(v).navigate(R.id.action_mainFragment_to_secondFragment, bundle);
    
    使用 safe args 接收参数方式
    Bundle arguments = getArguments();
    if (arguments != null) {
        SecondFragmentArgs secondFragmentArgs = SecondFragmentArgs.fromBundle(arguments);
        String userName = secondFragmentArgs.getUserName();
        int age = secondFragmentArgs.getAge();
        tvUserName.setText(userName);
        tvAge.setText(String.valueOf(age));
    }
    

    总结:正如 插件 safe args 名称所代表的意思,它的主要好处在于安全的参数类型。Getter 和 Setter 的方式令参数的操作更友好,更直观,且更安全

    NavigationUI的使用方法

    1.NavigationUI存在的意义

    导航图是 Navigation 组件中很重要的一部分,它可以帮助快速了解页面之间的关系,再通过 NavController 便可以完成页面的切换工作。而在页面的切换过程中,通常还伴随着 App bar 中 menu 菜单的变化。对于不同的页面,App bar 中的 menu 菜单很可能是不一样的。 App bar 中的各种按钮和菜单,同样承担着页面切换的工作。例如,当 ActionBar 左边的返回按钮被单击时,需要响应该事件,返回到上一个页面,既然 Navigation 和 App bar 都需要处理页面切换事件,那么,为了方便管理, Jetpack 引入了 NavigationUI 组件,使 App bar 中的按钮和菜单能够于导航图中的页面关联起来。

    2.案例分析

    假设有两个页面:OneTestFragment 和 TwoTestFragment。这两个 Fragment 同属于 TestActivity。OneTestFragment 的 ActionBar 右边有一个按钮,通过该按钮,可以跳转到 TwoTestFragment。而在 TwoTestFragment 的 ActionBar 左侧有一个返回按钮,通过该按钮,可以返回 OneTestFragment。

    项目结构 image.png 通过导航图文件 nav_graph_test.xml,可以清晰地看到页面间的关系。TestActivity 包含了 OneTestFragment 和 TwoTestFragment。默认加载的是 OneTestFragment 。
    <?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_test"
        app:startDestination="@id/oneTestFragment">
    
        <fragment
            android:id="@+id/oneTestFragment"
            android:name="com.jinxin.navigation.test.OneTestFragment"
            android:label="fragment_one_test"
            tools:layout="@layout/fragment_one_test" />
    
        <fragment
            android:id="@+id/twoTestFragment"
            android:name="com.jinxin.navigation.test.TwoTestFragment"
            android:label="fragment_two_test"
            tools:layout="@layout/fragment_two_test" />
        
    </navigation>
    

    在 menu_settitngs.xml 文件中,为 ActionBar 添加菜单。注意,<item/>的 id 与 导航图中 TwoTestFragment的 id 是一致的,这表示,当该<item/>被单击时,将会跳转到 id 所对应的 Fragment,即 TwoTestFragment。

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item
            android:id="@+id/twoTestFragment"
            android:icon="@drawable/ic_launcher_background"
            android:title="第二个界面"/>
    
    </menu>
    

    在 TestActivity 中实例化菜单并使用 NavigationUI 组件处理被单击的菜单项的跳转逻辑

    public class TestActivity extends AppCompatActivity {
    
        private static final String TAG = "TestActivity";
    
        private NavController navController;
        private AppBarConfiguration appBarConfiguration;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
    
            // NavController 用于页面的导航和切换
            navController = Navigation.findNavController(this, R.id.nav_host_fragment_test);
            // AppBarConfiguration 用于 Appbar 的配置
            appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
            // 将 Appbar 和 NavController绑定起来
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            // 实例化菜单
            getMenuInflater().inflate(R.menu.menu_setting, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(@NonNull MenuItem item) {
            Log.d(TAG, "onOptionsItemSelected: ");
            // 由于再导航图和菜单的布局文件中,已经为TwoTestFragment设置好了相同的id(即twoTestFragment)
            // 因此,在onOptionsItemSelected()方法中,通过NavigationUI便可以自动完成页面跳转
            return NavigationUI.onNavDestinationSelected(item, navController) || super.onOptionsItemSelected(item);
        }
    
        @Override
        public boolean onSupportNavigateUp() {
            Log.d(TAG, "onSupportNavigateUp: ");
            // 覆盖onSupportNavigationUp()方法,当在SettingsFragment中单击ActionBar左边的返回按钮时,
            // NavigationUI可以帮助settingsFragment回到MainFragment
            return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
        }
    }
    

    需要注意的是,在示例中,App bar 是在 TestActivity 中进行管理的。当从 OneTestFragment 跳转到 TwoTestFragment 时,需要在 TwoTestFragment 中覆盖 onCreateOptionsMenu()方法,并在该方法中清除 TwoTestFragment 所对应的menu。

    public class TwoTestFragment extends Fragment {
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_two_test, container, false);
        }
    
        @Override
        public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
            // 清除menu
            menu.clear();
            super.onCreateOptionsMenu(menu, inflater);
        }
    }
    

    Jetpack 提供了 OnDestinationChangedListener 接口,用来监听页面切换事件

    navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
        @Override
        public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
            Log.d(TAG, "onDestinationChanged: 切换事件");
        }
    });
    
    3.扩展延伸

    NavigationUI 对 3 种类型的 App bar 提供了支持,以上代码一 ActionBar 为例,稍作修改,便可以支持另外两种 App bar。3 种 App bar:

    ActionBar、Toolbar、CollapsingToolbarLayout

    除了最常见的 menu 菜单,NavigationUI 还可以配合另外两种菜单使用。

    App bar 左侧的抽屉菜单(DrawLayout + NavigationView)、底部菜单(ButtonNavigationView)

    深层链接DeepLink

    1.DeepLink 的两种应用场景

    Navigation 组件还有一个非常重要和使用的特性 DeepLink,通过该特性,可以利用 PendingIntent 或一个真实的 URL 链接,直接跳转到应用程序中的某个页面(Activity/Fragment)

    • PendingIntent 的方式。当应用程序接收到某个通知推送,你希望点击该通知时,能够直接跳转到展示该通知内容的页面,那么可以通过 PendingIntent 来完成此操作。
    • URL 的方式。当用户通过手机浏览器网站上的某个页面时,可以在网页上放置一个类似于 “在应用内打开” 的按钮。如果用户的手机安装有对应的应用程序,那么通过 DeepLink 就能打开相应的页面;如果没有安装,那么网站可以导航到应用程序的下载页面,从而引导用户按钮应用程序
    2.PendingIntent的方式

    向通知栏发送一条通知,模拟用户收到一条推送的情况,当通知被点击时,系统会自动打开在 PendingIntent 中设置到的目的地

    public class MainFragment extends Fragment {
    
        private static final String CHANNEL_ID = "1";
        private static final int notificationId = 8;
    
        public MainFragment() {
            // Required empty public constructor
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            if (getArguments() != null) {
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_main, container, false);
    
            view.findViewById(R.id.btn_send_notification).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    sendNotification();
                }
            });
            return view;
        }
    
        /**
         * 向通知栏发送一条通知,模拟用户收到一条推送的情况
         */
        private void sendNotification() {
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                int importanceDefault = NotificationManager.IMPORTANCE_DEFAULT;
                NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "ChannleName", importanceDefault);
                channel.setDescription("description");
                NotificationManager notificationManager = getActivity().getSystemService(NotificationManager.class);
                notificationManager.createNotificationChannel(channel);
            }
    
            NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity(), CHANNEL_ID)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setContentTitle("DeepLinkDemo")
                    .setContentText("Test")
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                    // 设置 PendingIntent
                    .setContentIntent(getPendingIntent())
                    .setAutoCancel(true);
    
            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(getActivity());
            notificationManagerCompat.notify(notificationId, builder.build());
        }
    
        /**
         * 构建PendingIntent对象
         * 在其中其中设置,当通知被点击时需要跳转到的目的地(destination),以及传递的参数
         * @return PendingIntent
         */
        private PendingIntent getPendingIntent() {
            Bundle bundle = new Bundle();
            bundle.putString("userName", "Michael");
            bundle.putInt("age", 30);
            return Navigation
                    .findNavController(requireActivity(), R.id.btn_send_notification)
                    .createDeepLink()
                    .setGraph(R.navigation.nav_graph)
                    .setDestination(R.id.secondFragment)
                    .setArguments(bundle)
                    .createPendingIntent();
        }
    }
    
    2.URL的方式

    1.在导航图中为页面添加<deepLink/>标签。在 app:uri 属性中填入页面的相应Web地址,后面的参数会通过 Bundle 对象传递到页面中。

    <fragment
        android:id="@+id/secondFragment"
        android:name="com.jinxin.navigation.SecondFragment"
        android:label="fragment_second"
        tools:layout="@layout/fragment_second" >
    
        <!-- 添加参数 -->
        <argument
            android:name="userName"
            app:argType="string"
            android:defaultValue='"unknown'/>
    
        <!-- 添加参数 -->
        <argument
            android:name="age"
            app:argType="integer"
            android:defaultValue="0"/>
    
        <!-- 为destination 添加<deepLink/>标签 -->
        <deepLink app:uri="test.deeplink.com/{userName}/{age}" />
    
    </fragment>
    

    2.为 Activity 设置<nav-graph/>标签。当用户在 Web 页面中访问Web地址时应用程序便能得到监听

    <activity android:name=".NavigationActivity" >
    
        <!-- 为Activity 设置<nav-graph/>标签-->
        <nav-graph android:value="@navigation/nav_graph"/>
    </activity>
    

    3.模拟使用URL访问应用程序特定的界面

    image.png

    总结

    Navigation 组件为页面切换 和 App bar 的变化提供了统一的解决方案。配合Android Studio,可以通过图形化的方式管理配置页面切换,甚至加入动画效果。页面切换通常还会伴随着参数传递,Android Studio 提供了 safe args插件,通过该插件,可以以更安全的方式在页面间传递参数。对于 App bar 中的菜单,Jetpack 提供了 NavigationUI 组件,该组件使 App bar 中的菜单能够与页面切换对应起来。最后,通过 DeepLink,可以使用 PendingIntent 或 URL 的方式跳转到应用程序中的某个特定的页面。

    相关文章

      网友评论

        本文标题:学习记录(3)- Navigation

        本文链接:https://www.haomeiwen.com/subject/rzromktx.html