现在我们需要使用 Navigation
里面的导航菜单,而不是使用默认 Activity
的导航菜单。
如果可以通过官网的方式学习,就尽量不要使用视频的方式,因为学习的时候大部分是学习最新的,而视频很大概率是很久以前的。
学到了两种方式。
提前做好准备,打开文件 res/navigation/
下你的 xml
文件,点击每一个 Fragment
页面,给它们设置对应的标题,在 Design
下的右边的 id
下,有一个属性是 label
,填写上对应的名称即可。
1. 使用 Activity
中的导航菜单
默认 Activity
的导航菜单显示的是标题和返回按钮,而返回按钮是返回到上一个 Activity
,而我们的 Navigation
是在一个 Activity
中的,如果当前 Activity
位于栈的最上层,我学习的代码就是让所有的 Fragment
都在 MainActivity
中,因为无论我怎么跳转都在 MainActivity
中。所以现在有两个两个任务:
- 首先跳转到下一页以后会出现返回按钮;
- 点击返回按钮能够正常返回上一个
Navigation
页面。
由于第二个需要在第一个完成的基础上才能看得出效果,所以我们按上面的步骤进行。
原本的效果:
打开承载了
Fragment
的 Activity
的 java
文件,我这里是 MainActivity.java
,在 onCreate
方法下添加如下代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}
android 官方获取 navController
是直接获取的 Navigation.findNavController(this, R.id.nav_host_fragment);
,如果很不幸你也这样写了,那么就会出现的错误:
Caused by: java.lang.IllegalStateException: Activity com.example.learnjetpack.MainActivity@b516fb8 does not have a NavController set on 2131230962
只要修改成我上面那样就可以解决这个问题,至于原因我现在解释不了,以后会补全。上面的代码就是托管原本 Activity
的 Bar
。
这样第一个完成了,至于第二个,只需要重写原本
Activity
的返回的逻辑:
@Override
public boolean onSupportNavigateUp() {
NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp();
}
接下来看看最终的效果。
我还遇到了一个问题,之前我的
MainActivity
的 theme
设置 android:theme="@style/Theme.AppCompat.Light.NoActionBar"
,结果出现了下面的错误:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.appcompat.app.ActionBar.setTitle(java.lang.CharSequence)' on a null object reference
把这个改掉即可,因为设置 NoActionBar
了,结果又让显示,固然手机就会耍小脾气。这个是在 AndroidManifest.xml
中设置的。
2. 使用 Toolbar
这种方式就是不用默认的,而是自定义;所以这个很容易想到需要将 MainActivity
的 theme
改为上面会出现错误的情况。打开 AndroidManifest.xml
文件,修改对应的 Activity
的 theme
,修改成 @style/Theme.AppCompat.Light.NoActionBar
。
打开对应的
Activity
下的布局文件,我这里是 MainActivity
,布局文件为 activity_layout.xml
,在 androidx.fragment.app.FragmentContainerView
上添加:
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="0dp"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:layout_constraintBottom_toTopOf="@+id/nav_host_fragment"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
先看看效果:
自定义头部的效果
接下来让其显示内容。
同样在 Activity
中的添加:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavHostFragment navHostFragment = (NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
NavController navController = navHostFragment.getNavController();
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()).build();
Toolbar toolbar = findViewById(R.id.toolbar);
NavigationUI.setupWithNavController(
toolbar, navController, appBarConfiguration);
}
这种方式 Navigation
会自动托管 Toolbar
,这样就可以轻松实现上面的效果,其他的代码就不需要,看效果:
网友评论