一:概述
在学习Google官网demo,sunflower其中用到了NavigationUI的相关实现,在自己实现的过程中顶层导航栏左侧的按钮总是或多或少的出现不同的问题(学的比较渣,于是自己调试了好几天,加之对于API的不熟悉,因此又拖慢了进程)
在我调试的过程中,关于toolbar左侧导航按钮的实现有两种办法。一种是用了ActionBarDrawerToggle的API实现,这个的功能只是实现了打开左侧导航栏然后完成相应的跳转之后在其后的其他活动或者(fragment)中就无作用,这只适合简单的跳转。而对于另一个API是AppBarConfiguration,因为我的demo来说,实现的是一个Activity作为底容器,实现多个fragment的跳转,并用到了Navigation相关组件,AppBarConfiguration配合这个demo实现,可以更有效的组织和导航相应的fragment。
二:ActionBarDrawerToggle的使用
在布局中添加ToolBar和NavigationView
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.PopupOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<fragment
android:id="@+id/garden_nav_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_garden"/>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
style="@style/Widget.MaterialComponents.NavigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_navigation"/>
</android.support.v4.widget.DrawerLayout>
在MainAcitivity的OnCreate()方法中实现
private Toolbar toolbar;
private ActivityMainBinding binding;
private NavController navController;
private AppBarConfiguration appBarConfiguration;
private DrawerLayout drawerLayout;
private NavigationView navView;
private ActionBarDrawerToggle toggle;
......
toolbar = binding.toolbar;
drawerLayout = binding.drawerLayout;
setSupportActionBar(toolbar);
navView = binding.navigationView;
toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
......
@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
......
实现效果如下:
三:AppBarConfiguration的使用
NavController |
AppBarConfiguration |
NavigationUI |
XML布局:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.PopupOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<fragment
android:id="@+id/garden_nav_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_garden"/>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
style="@style/Widget.MaterialComponents.NavigationView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_navigation"/>
</android.support.v4.widget.DrawerLayout>
</layout>
截下来就是代码的实现,相关的说明在代码的注释中体现:
package com.example.mysunflower;
import android.databinding.DataBindingUtil;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.example.mysunflower.databinding.ActivityMainBinding;
import static androidx.navigation.ui.NavigationUI.setupActionBarWithNavController;
public class MainActivity extends AppCompatActivity {
/*
* NavController绑定容纳fragment的容器,实现对于多个Fragment的控制
*
* 以下代码涉及到AppBarConfiguration, Toolbar, 左侧导航栏NavigationView
* 大体过程就是将这几个可视化或自动管理的组件与NavController关联,实现对多个fragment的有效组织管理
* */
private ActivityMainBinding binding;
/*
* 用Navigation构建项目时,用到的一些API
* 具体使用方法请参考官方文档
* */
private NavController navController;
private AppBarConfiguration appBarConfiguration;
private DrawerLayout drawerLayout;
/*
* 简单的单界面跳转API,作为测试使用
* */
private ActionBarDrawerToggle toggle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
/*
* 实例化
* */
drawerLayout = binding.drawerLayout;
navController = Navigation.findNavController(this, R.id.garden_nav_fragment);
/*
* 配置AppBarConfiguration
* 将其于navController的实现,与主布局绑定,其内部自动实现相应功能
* */
appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph())
.setDrawerLayout(drawerLayout)
.build();
/*
* 添加toolbar的支持
* */
setSupportActionBar(binding.toolbar);
/*setupActionBarWithNavController(this, navController);*/
/*
* 用NavigationUI将toolbar与appBarConfiguration,toolbar会自动切换相应fragment的名称
* */
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
/*toggle = new ActionBarDrawerToggle(this, drawerLayout, binding.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();*/
/*
* 将左侧导航栏与navController绑定
* */
NavigationUI.setupWithNavController(binding.navigationView, navController);
LoadNavItemSelListener();
}
/*
* 实现程序的后退功能
* 将AppBarConfiguration与navController,传递到NavigationUI.navigateUp()实现顶部导航栏左侧对于fragment切换的管理
* */
@Override
public boolean onSupportNavigateUp() {
NavigationUI.navigateUp(navController, appBarConfiguration);
/*
* 注意:此注释处调用了其他API下的函数,导致整个功能实现异常
* 前期也因为自己对API的不熟悉,在此处浪费了大量时间,一定不能调错函数
* */
/*
return navController.navigateUp() || super.onSupportNavigateUp();
*/
return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
}
/*@Override
public void onBackPressed() {
super.onBackPressed();
if (drawerLayout == null){
Log.d(String.valueOf(MainActivity.this), "onBackPressed: drawerLayout == null");
}
if (drawerLayout.isDrawerOpen(binding.navigationView)){
drawerLayout.closeDrawer(binding.navigationView);
}else {
super.onBackPressed();
}
}*/
@Override
public void onBackPressed() {
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
private void LoadNavItemSelListener() {
binding.navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.garden_fragment:
navController.navigate(R.id.action_gardenFragment_to_plantDetailFragment);
break;
case R.id.plant_list_fragment:
navController.navigate(R.id.action_gardenFragment_to_plantListFragment2);
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_toolbar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
}
笔者只是初入Android开发的小白,若有错误之处请多多包含,当然更希望大家批评指正,谢谢。