一直以来我写的 Android App 都是用一个 Activity 承接一个页面的业务逻辑,代码越写越多,各种 Activity 之间的跳转也非常混乱了,甚至到了难以维护的程度。
借着这个学习的机会,我觉得自己是应该好好了解一下 Android Navigation 了,这篇博客主要参考 Android Developer Website 的文档,当然还有我学习过程中踩到的坑的一个记录。最后就是对于 Navigation + BottomNavigationView 的一个综合使用过程。为之后的 Android 应用架构搭建打下基础,与君共勉。
首先在使用 Navigation 之前得先了解一下 Navigation 能干什么,我要用它来达到什么目的。
目前来说,我的需求主要是各各 Activity 之间跳转混乱,使用 Navigation 能够实现一个 Activity 多 Fragment 的架构。方便统一管理页面,修改页面实现不影响路由跳转。
首先将依赖加入到项目的 app/build.gradle 中
dependencies {
def nav_version = "2.3.5"
// 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:2.4.0-alpha10"
}
然后我们可以使用 Android Studio 来创建 navigation 资源文件,具体操作步骤如下
选择 res 文件夹 -> New -> Android Resource File
File name 处输入文件名,我这里就参考官网文档输入 nav_graph ,Resource type 选择 Navigation,然后点击 OK 创建资源文件即可。
创建成功后我们能看到 res 文件夹下多了一个 navigation 文件夹和 nav_graph.xml 资源文件,打开 nav_graph.xml 文件点击 Design 就能直接使用 Android studio 的 Navigation Editor 工具,提供了非常方便的可视化编辑工具(到这里导航资源文件就创建成功了)
现在我们先去修改 MainActivity 和创建几个 Fragment 用来实现测试布局。
我这里一共创建了两个 Fragment 作为页面,并且每个页面给了一个提示文本代表这是不同的页面。上面就是页面布局以及代码文件。
HomeFragment(主页)
UserFragment(用户页面)
创建好 Fragment 之后打开 nav_graph.xml 文件将刚创建的两个 Fragment 添加进去,可视化操作的话直接点击上面的小图标,将 HomeFragment 和 UserFragment 依次添加进去就好了。当然也可以手写 fragment 节点到 navigation 节点下。
<?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/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.pbkhub.smartcity.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/userFragment"
android:name="com.pbkhub.smartcity.UserFragment"
android:label="fragment_user"
tools:layout="@layout/fragment_user" />
</navigation>
fragment 节点的属性解析:
android:id 可以看作是一个唯一的路由 ID,跳转页面时会用到,通过 R.id.xxxx 方式引用
android:name 对应实现的 fragment 对象
android:label 描述标签
tools:layout fragment 布局文件
之后我们有新的页面就加入到这个文件中就好了(nav_graph.xml 中的导航不止可以用 fragment 还能添加 Activity)。
navigation 的 app:startDestination 属性可以指定默认启动的导航
接下来修改 MainActivity 的布局文件,我使用 FragmentContainerView 作为 Fragment 加载容器,在页面底部添加了两个按钮用来实现使用 navigation 跳转不同的页面。
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/a_main_nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<Button
android:id="@+id/a_main_btn_openhome"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="打开主页" />
<Button
android:id="@+id/a_main_btn_openuser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="30dp"
android:text="用户页面" />
</LinearLayout>
</LinearLayout>
到这里,我们的布局基本搞定。接下来就是实现点击按钮切换不同页面了。
通过调用 getSupportFragmentManager().findFragmentById() 方法传如入 FragmentContainerView 的 View id 获取 NavHostFragment 对象,调用 NavHostFragment 对象的 getNavController() 方法就能获取 NavController 对象。
然后调用 initView() 方法初始化组件以及给底部的 Button 绑定点击事件,调用 NavController 对象的 navigate() 方法传入在 nav_graph.xml 中定义 fragment 节点的 id 就能切换到指定的 fragment 了。具体的实现可以参考下面的代码
package com.pbkhub.smartcity;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentContainerView;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
FragmentContainerView mNavHost;
Button mOpenHome, mOpenUser;
NavHostFragment navHostFragment;
NavController navController;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.a_main_nav_host);
navController = navHostFragment.getNavController();
initView();
}
private void initView() {
mNavHost = findViewById(R.id.a_main_nav_host);
mOpenHome = findViewById(R.id.a_main_btn_openhome);
mOpenUser = findViewById(R.id.a_main_btn_openuser);
mOpenUser.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
navController.navigate(R.id.userFragment);
}
});
mOpenHome.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
navController.navigate(R.id.homeFragment);
}
});
}
}
好了,今天关于 Navigation 简单使用的博客就先写到这里吧,如果不鸽的话我还会写一下 Navigation + BottomNavigationView 的使用。
上面的示例代码放到 GitHub 了,如果有需要看看的可以自取:https://github.com/PBK-B/android-use-navigation-demo
如果遇到了问题欢迎到我的博客 https://bin.zmide.com/?p=967 给我留言,每条留言都会回的哦 ?。
全部评论:1条