一、Navigation
1、Navigation 概述
- Navigation 是 Jetpack 中的一个重要成员,它主要是结合导航图(Navigation Graph)来控制和简化 Fragment 之间的导航,即往哪里走,该怎么走
2、Navigate 引入
- 在模块级
build.gradle
中引入相关依赖
implementation 'androidx.navigation:navigation-fragment:2.3.5'
implementation 'androidx.navigation:navigation-ui:2.3.5'
二、Navigation 跳转实例实操
- 有三个 Fragment 实现 Navigation 跳转,它们分别是 MoreJumpOneFragment、MoreJumpTwoFragment、MoreJumpThreeFragment
-
在 MoreJumpOneFragment 中,可以前进到 MoreJumpTwoFragment
-
在 MoreJumpTwoFragment 中,可以前进到 MoreJumpThreeFragment,也可以后退到 MoreJumpOneFragment
-
在 MoreJumpThreeFragment 中,可以后退到 MoreJumpTwoFragment,也可以直接后退到 MoreJumpOneFragment
2、具体实现
(1)Fragment Layout
- fragment_more_jump_one.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=".fragment.MoreJumpOneFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MoreJumpOneFragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="前进"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- fragment_more_jump_two.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=".fragment.MoreJumpTwoFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MoreJumpTwoFragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_go"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="前进"
app:layout_constraintBottom_toTopOf="@+id/btn_back"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="后退"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- fragment_more_jump_three.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=".fragment.MoreJumpThreeFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MoreJumpThreeFragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="后退"
app:layout_constraintBottom_toTopOf="@+id/btn_back_to_one"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_back_to_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="后退到 one"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
(2)Fragment Code
- MoreJumpOneFragment.java
package com.my.navigation.fragment;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.my.navigation.R;
public class MoreJumpOneFragment extends Fragment {
private NavController navController;
private Button btnGo;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_more_jump_one, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
btnGo = view.findViewById(R.id.btn_go);
btnGo.setOnClickListener(v -> navController.navigate(R.id.action_moreJumpOneFragment_to_moreJumpTwoFragment));
}
}
- MoreJumpTwoFragment.java
package com.my.navigation.fragment;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.my.navigation.R;
public class MoreJumpTwoFragment extends Fragment {
private NavController navController;
private Button btnGo;
private Button btnBack;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_more_jump_two, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
btnGo = view.findViewById(R.id.btn_go);
btnBack = view.findViewById(R.id.btn_back);
btnGo.setOnClickListener(v -> navController.navigate(R.id.action_moreJumpTwoFragment_to_moreJumpThreeFragment));
btnBack.setOnClickListener(v -> navController.navigateUp());
}
}
- MoreJumpThreeFragment.java
package com.my.navigation.fragment;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.my.navigation.R;
public class MoreJumpThreeFragment extends Fragment {
private NavController navController;
private Button btnBack;
private Button btnBackToOne;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_more_jump_three, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
navController = Navigation.findNavController(view);
btnBack = view.findViewById(R.id.btn_back);
btnBackToOne = view.findViewById(R.id.btn_back_to_one);
btnBack.setOnClickListener(v -> navController.navigateUp());
btnBackToOne.setOnClickListener(v -> navController.popBackStack(R.id.moreJumpOneFragment, false));
}
}
(3)Navigation Graph
- my_graph_more_jump.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/my_graph_more_jump"
app:startDestination="@id/moreJumpOneFragment">
<fragment
android:id="@+id/moreJumpOneFragment"
android:name="com.my.navigation.fragment.MoreJumpOneFragment"
android:label="fragment_more_jump_one"
tools:layout="@layout/fragment_more_jump_one">
<action
android:id="@+id/action_moreJumpOneFragment_to_moreJumpTwoFragment"
app:destination="@id/moreJumpTwoFragment" />
</fragment>
<fragment
android:id="@+id/moreJumpTwoFragment"
android:name="com.my.navigation.fragment.MoreJumpTwoFragment"
android:label="fragment_more_jump_two"
tools:layout="@layout/fragment_more_jump_two">
<action
android:id="@+id/action_moreJumpTwoFragment_to_moreJumpThreeFragment"
app:destination="@id/moreJumpThreeFragment" />
</fragment>
<fragment
android:id="@+id/moreJumpThreeFragment"
android:name="com.my.navigation.fragment.MoreJumpThreeFragment"
android:label="fragment_more_jump_three"
tools:layout="@layout/fragment_more_jump_three">
<action
android:id="@+id/action_moreJumpThreeFragment_to_moreJumpOneFragment"
app:destination="@id/moreJumpOneFragment" />
</fragment>
</navigation>
(4)Activity Layout
- activity_more_jump.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=".MoreJumpActivity">
<fragment
android:id="@+id/nhf"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/my_graph_more_jump" />
</androidx.constraintlayout.widget.ConstraintLayout>
(5)Activity Code
- MoreJumpActivity.java
package com.my.navigation;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MoreJumpActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_more_jump);
}
}
三、Navigation 跳转详解
1、Navigation 跳转方法
-
void navigate(@IdRes int resId)
:该方法用于根据在导航图中定义的 action 的 ID 进行 Fragment 跳转 -
boolean navigateUp()
:该方法用于返回到上一个 Fragment -
boolean popBackStack(@IdRes int destinationId, boolean inclusive)
:该方法用于活动栈中弹出 Fragment,直到到达指定的 Fragment,如果 inclusive 被设置为 true,则指定的 Fragment 也会被从活动栈中移除
2、Navigation 活动栈解析
- 一开始在 MoreJumpOneFragment 中时,此时的活动栈
MoreJumpOneFragment
- 当在 MoreJumpOneFragment 中,前进到 MoreJumpTwoFragment 时,此时的活动栈
MoreJumpTwoFragment
MoreJumpOneFragment
- 当在 MoreJumpTwoFragment 中,前进到 MoreJumpThreeFragment 时,此时的活动栈
MoreJumpThreeFragment
MoreJumpTwoFragment
MoreJumpOneFragment
- 当在 MoreJumpThreeFragment 中,后退到 MoreJumpOneFragment 时,此时的活动栈
MoreJumpThreeFragment
四、Navigation 跳转补充
1、Navigation 跳转方法补充
- 在 MoreJumpThreeFragment 中,直接后退到 MoreJumpOneFragme,除了使用 popBackStack 方法,还可以用如下方法
NavOptions navOptions = new NavOptions.Builder().setPopUpTo(R.id.moreJumpOneFragment, true).build();
navController.navigate(R.id.action_moreJumpThreeFragment_to_moreJumpOneFragment, null, navOptions);
2、Navigation 跳转方法解析
NavOptions navOptions = new NavOptions.Builder().setPopUpTo(R.id.moreJumpOneFragment, true).build();
- 使用
NavOptions.Builder
创建一个 NavOptions 对象,它是跳转行为
-
该对象指定了在导航到 moreJumpOneFragment 时,清除活动栈中所有 moreJumpOneFragment 之上的 Fragment
-
其中,
Builder setPopUpTo(@IdRes int destinationId, boolean inclusive)
方法中的 inclusive 被设置为 true,表示包括 moreJumpOneFragment 本身也被清除 -
因为要跳转到 moreJumpOneFragment,所以并不会真正导致 moreJumpOneFragment 从活动栈中被清楚,但所有在它之上的 Fragment 都会被清除,导致看起来就像是直接跳转到了moreJumpOneFragment
navController.navigate(R.id.action_moreJumpThreeFragment_to_moreJumpOneFragment, null, navOptions);
- 通过
void navigate(@IdRes int resId, @Nullable Bundle args, @Nullable NavOptions navOptions)
方法进行跳转,需要传递 3 个参数,分别为导航图中定义的 action 的 ID、携带数据、跳转行为