实践

Navigation学习【一】——简单使用

2020-02-02  本文已影响0人  12313凯皇

Navigation的简单使用Demo

导航概述

导航组件由三个关键部分组成,它们相互协调工作。他们是:

导航时,将使用NavController对象,在“导航图”中告诉它您想去的地方或要走的路径。然后,NavController它将在NavHostFragment中显示适当的目的地。

注意:如果要使用导航和 Android Studio,则必须使用 Android Studio 3.3 或更高版本。

导入

获取最新版本

appbuild.gradle 中添加依赖:

dependencies {
  def nav_version = "2.1.0"

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

}

使用

  1. 创建导航图nav_graph.xml

    在“Project”窗口中,右键点击 res 目录,然后依次选择 New > Android Resource File。此时系统会显示 New Resource File 对话框。在 File name 字段中输入名称,例如“nav_graph”。从 Resource type 下拉列表中选择 Navigation,然后点击 OK。

nav_graph.png
  1. Activity 添加 NavHost
<!-- activity_main.xml -->
<?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=".MainActivity">

    <!-- 添加导航activity -->
    <fragment
        android:id="@+id/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"/>
</androidx.constraintlayout.widget.ConstraintLayout>

下面对三个比较重要的属性做一下解释:

  1. 设置起始目的地

    res/navigation/nav_graph.xml中通过startDestination设置起始fragment,当然这里也可以通过design模式通过点击相关图标去设置,这里不好演示就通过展示代码来实现。

    <!-- nav_graph.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/nav_graph"
        app:startDestination="@id/firstFragment">
    
        <fragment
            android:id="@+id/firstFragment"
            android:name="com.yu.hu.demotest.FirstFragment"
            android:label="fragment_first"
            tools:layout="@layout/fragment_first" />
    
       
    </navigation>
    

ok,到了这里项目就可以正常运行了。

简单跳转

  1. res/navigation/nav_graph.xml中设置跳转Action

    <!-- nav_graph.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/nav_graph"
        app:startDestination="@id/firstFragment">
    
        <fragment
            android:id="@+id/firstFragment"
            android:name="com.yu.hu.demotest.FirstFragment"
            android:label="fragment_first"
            tools:layout="@layout/fragment_first" >
            
            <!-- 设置跳转至secondFragment的action 
             id  -- action的id
             destination -- 设置目的地
                enterAnim|exitAnim|popEnterAnim|popExitAnim 为相应的切换动画
             -->
            <action
                android:id="@+id/action_firstFragment_to_secondFragment"
                app:destination="@id/secondFragment"
                app:enterAnim="@anim/nav_default_enter_anim"
                app:exitAnim="@anim/nav_default_exit_anim"
                app:popEnterAnim="@anim/nav_default_pop_enter_anim"
                app:popExitAnim="@anim/nav_default_pop_exit_anim" />
        </fragment>
    
        <fragment
            android:id="@+id/secondFragment"
            android:name="com.yu.hu.demotest.SecondFragment"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" />
    </navigation>
    
  2. 使用Navigation实现跳转逻辑

    核心代码:Navigation.findNavController(view).navigate(R.id.viewTransactionsAction);

    //FirstFragment.java
    public class FirstFragment extends Fragment {
    
        private View mView;
    
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            mView = inflater.inflate(R.layout.fragment_first, container, false);
            return mView;
        }
    
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            Button jumpBtn = mView.findViewById(R.id.jump_btn);
            jumpBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    NavController navController = Navigation.findNavController(mView);
                    //action_firstFragment_to_secondFragment 之前设置的action id
                    navController.navigate(R.id.action_firstFragment_to_secondFragment);
                }
            });
    
            //对于点击事件还可以这么做
            //jumpBtn.setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_firstFragment_to_secondFragment));
        }
    }
    

传递参数

  1. res/navigation/nav_graph.xml设置所需参数

    <!-- nav_graph.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/nav_graph"
        app:startDestination="@id/firstFragment">
    
        ...
    
        <fragment
            android:id="@+id/secondFragment"
            android:name="com.yu.hu.demotest.SecondFragment"
            android:label="fragment_second"
            tools:layout="@layout/fragment_second" >
    
            <!-- 
             设置此fragment所需参数
             name  -- name
             argType -- 参数类型
             nullable  -- 是否可为空
             defaultValue  -- 默认值
                 -->
            <argument
                android:name="content"
                app:argType="string"
                app:nullable="true"
                android:defaultValue="second_fragment" />
        </fragment>
    </navigation>
    

Navigation 库支持以下参数类型:

类型 app:argType 语法 是否支持默认值? 是否支持 null 值?
整数 app:argType="integer"
浮点数 app:argType="float"
长整数 app:argType="long" 是 - 默认值必须始终以“L”后缀结尾(例如“123L”)。
布尔值 app:argType="boolean" 是 -“true”或“false”
字符串 app:argType="string"
资源引用 app:argType="reference" 是 - 默认值必须为“@resourceType/resourceName”格式(例如,“@style/myCustomStyle”)或“0”
自定义 Parcelable app:argType="<type>",其中 <type> 是 Parcelable 的完全限定类名称 支持默认值“@null”。不支持其他默认值。
自定义 Serializable app:argType="<type>",其中 <type> 是 Serializable 的完全限定类名称 支持默认值“@null”。不支持其他默认值。
自定义 Enum app:argType="<type>",其中 <type> 是 Enum 的完全限定名称 是 - 默认值必须与非限定名称匹配(例如,“SUCCESS”匹配 MyEnum.SUCCESS)。
  1. 启动并传参

    • 不使用Safe Args

      //发送方通过bundle存储数据并通过navigate方法传递
      Button jumpBtn = mView.findViewById(R.id.jump_btn);
      jumpBtn.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              NavController navController = Navigation.findNavController(mView);
              //action_firstFragment_to_secondFragment 之前设置的action id
              Bundle bundle = new Bundle();
              bundle.putString("content","from firstFragment");
              navController.navigate(R.id.action_firstFragment_to_secondFragment,bundle);
          }
      });
      
      //接收方:
      TextView textView = mView.findViewById(R.id.second_tv);
      textView.setText(getArguments().getString("content"));
      

混淆

补充

//activity中获取NavController  第二个参数为navigation的id
NavController navController = Navigation.findNavController(this, R.id.nav_graph);
navController.handleDeepLink(new Intent());

参考文章

上一篇 下一篇

猜你喜欢

热点阅读