本文由 Luzhuo 编写,转发请保留该信息.
原文: https://blog.csdn.net/Rozol/article/details/90487113
Google官方出品的侧滑导航栏, 可替换长期未维护的SlidingMenu.
除此之外, 还有个第三方开源库MaterialDrawer可供选择
Navigation Drawer
是 Material Design
中的侧滑导航栏, 由抽屉布局 DrawerLayout
和 导航View NavigationView
组成.
Navigation Drawer Activity
Navigation Drawer Activity
其中 NavigationView 的 android:layout_gravity="start"
属性控制左右滑方向.
DrawerLayout 与 Toolbar 的结合
private DrawerLayout drawer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
initDrawerLayout();
}
private void initDrawerLayout() {
// --- DrawerLayout 与 Toolbar 的结合 ---
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
}
返回键的处理
@Override
public void onBackPressed() {
if (drawer == null) return;
// 返回键: 侧滑开着就将其关闭, 关着则退出应用
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
打开 / 关闭 / 锁定
// 打开
drawer.openDrawer(GravityCompat.START);
drawer.openDrawer(GravityCompat.END);
drawer.openDrawer(GravityCompat.START, true); // 默认true, 执行动画
drawer.openDrawer(navigationView); // 打开指定的 navigationView
// 关闭
drawer.closeDrawer(GravityCompat.START);
drawer.closeDrawers(); // 关闭所有
// 打开并锁定
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN, GravityCompat.START);
参数 | Description |
---|---|
GravityCompat.START | 左侧打开 |
GravityCompat.END | 右侧打开 |
— | — |
DrawerLayout.LOCK_MODE_LOCKED_CLOSED | 关闭锁 (锁着, 不让手势打开) |
DrawerLayout.LOCK_MODE_LOCKED_OPEN | 开启锁 (开着, 不让手势关闭) |
DrawerLayout.LOCK_MODE_UNDEFINED | 默认锁 (默认是不上锁) |
DrawerLayout.LOCK_MODE_UNLOCKED | 不锁 (不上锁) |
注意: 使用方向(如: GravityCompat.START) 参数时, 子布局必须有指定layout_gravity属性(如: NavigationView 的 android:layout_gravity="start"
)与之相匹配, 否则会找不到.
阴影的颜色
// (被遮挡部分的)阴影部分的颜色
drawer.setScrimColor(Color.parseColor("#66666666"));
监听滑动事件
drawer.addDrawerListener(drawerListener);
private DrawerLayout.DrawerListener drawerListener = new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View view, float v) {
Log.i(TAG, "onDrawerSlide: 滑动时:" + v);
}
@Override
public void onDrawerOpened(@NonNull View view) {
Log.i(TAG, "onDrawerOpened: 打开后");
}
@Override
public void onDrawerClosed(@NonNull View view) {
Log.i(TAG, "onDrawerClosed: 关闭后");
}
@Override
public void onDrawerStateChanged(int i) {
// 滑动状态
switch (i){
case DrawerLayout.STATE_DRAGGING:
Log.i(TAG, "onDrawerStateChanged: 滑动状态");
break;
case DrawerLayout.STATE_IDLE:
Log.i(TAG, "onDrawerStateChanged: 静止状态");
break;
case DrawerLayout.STATE_SETTLING:
// 设置状态在静止状态之前调用, 表示正在调整到最终位置
Log.i(TAG, "onDrawerStateChanged: 设置状态");
break;
default:
break;
}
}
};
标准的导航菜单, NavigationView 通常放在 DrawerLayout 中使用.
上部分是Header, 下部分是Menu, 当然这些都是可选的.
Menu具有不错的默认样式: 选中效果 / 分组 / 分组子标题 / Header 等.
DrawerLayout是v4包下的, 而 NavigationView 则是design包下的.
implementation 'com.android.support:design:28.0.0'
添加Header和Menu布局
通过app:headerLayout
属性添加Header;
通过app:menu
属性添加Menu.
编写Menu布局
Header就是普通的布局没什么好讲的, 这里讲下Menu的编写.
文件放在 res -> menu
文件夹下.
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
// 有选中效果的菜单组
<group android:checkableBehavior="single">
// 名称
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
group>
// 没有选中效果的普通菜单条目, title子标题
<item android:title="Communicate">
<menu> // 子菜单
// 标题
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="Send" />
menu>
item>
menu>
设置Menu的选择监听
但用户选择完之后需要手动将侧滑导航栏关闭.
private void intiDrawerView() {
navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_camera:
break;
case R.id.nav_gallery:
break;
case R.id.nav_slideshow:
break;
case R.id.nav_manage:
break;
case R.id.nav_share:
break;
case R.id.nav_send:
break;
default:
break;
}
// 关闭侧滑导航栏
drawer.closeDrawer(GravityCompat.START);
return true;
}
默认的情况下, 用户不点, Menu是没有选中的Item的, 可以通过setCheckedItem(int id)
方法设置选中. 且 onNavigationItemSelected
是不会回调的.
// 设置第一个选中
navigationView.setCheckedItem(R.id.nav_camera);
去除图标颜色显示规则, 显示为原色:
// 去除图标颜色显示规则, 显示为原色
navigationView.setItemIconTintList(null);
指定图标颜色显示规则(显示不同颜色):
在drawable
下创建nav_menu_icon_color
选择器资源文件.
// 有-为未选中的颜色, 没有-为选中的颜色
int[][] states = new int[][]{new int[]{-android.R.attr.state_checked},new int[]{android.R.attr.state_checked} };
int[] colors = new int[]{getResources().getColor(R.color.colorPrimaryDark), getResources().getColor(R.color.colorAccent) };
ColorStateList colorStateList = new ColorStateList(states, colors);
navigationView.setItemIconTintList(colorStateList);
指定图标的显示规则(显示不同图标):
// 未找到相关方法, 目前不支持
虽然系统未提供相关方法, 都是你可以通过修改图标自行实现, 就是麻烦些.
// 修改图标
navigationView.getMenu().findItem(R.id.nav_camera).setIcon(R.mipmap.menu_caomei);
设置的设置方法与图标是一样的, 这样不展开讲了.
navigationView.setItemTextColor(colorStateList);