Android NavigationDrawer(侧滑导航栏 DrawerLayout + NavigationView)
本文由 Luzhuo 编写,转发请保留该信息.
原文: https://blog.csdn.net/Rozol/article/details/90487113
Google官方出品的侧滑导航栏, 可替换长期未维护的SlidingMenu.
除此之外, 还有个第三方开源库MaterialDrawer可供选择
Navigation Drawer
是 Material Design
中的侧滑导航栏, 由抽屉布局 DrawerLayout
和 导航View NavigationView
组成.
快速创建
- 新建项目时:
- 新建项目时, 最后一页"Add an Activity to Mobile" 选择
Navigation Drawer Activity
- 新建项目时, 最后一页"Add an Activity to Mobile" 选择
- 新建Activity时:
- 在已有的项目, 创建Activity选择
Navigation Drawer Activity
- 在已有的项目, 创建Activity选择
手撸实现
抽屉布局 DrawerLayout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:openDrawer="start"><includelayout="@layout/app_bar_base"android:layout_width="match_parent"android:layout_height="match_parent" /><android.support.design.widget.NavigationViewandroid:id="@+id/nav_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"android:fitsSystemWindows="true"app:headerLayout="@layout/nav_header_base"app:menu="@menu/activity_base_drawer" /></android.support.v4.widget.DrawerLayout>
其中 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() {@Overridepublic void onDrawerSlide(@NonNull View view, float v) {Log.i(TAG, "onDrawerSlide: 滑动时:" + v);}@Overridepublic void onDrawerOpened(@NonNull View view) {Log.i(TAG, "onDrawerOpened: 打开后");}@Overridepublic void onDrawerClosed(@NonNull View view) {Log.i(TAG, "onDrawerClosed: 关闭后");}@Overridepublic 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;}}
};
导航View NavigationView
标准的导航菜单, 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.
<android.support.design.widget.NavigationViewandroid:id="@+id/nav_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"android:fitsSystemWindows="true"app:headerLayout="@layout/nav_header_base"app:menu="@menu/activity_base_drawer" />
编写Menu布局
Header就是普通的布局没什么好讲的, 这里讲下Menu的编写.
文件放在 res -> menu
文件夹下.
<?xml version="1.0" encoding="utf-8"?>
<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_camera"android:icon="@drawable/ic_menu_camera" // 图标android:title="Import" /> // 名称<item