DrawerLayout是support.v4包中实现侧滑菜单效果的控件,之前实现侧滑使用的是SlidingMenu,下面我主要介绍一下DrawerLayout控件。
DrawerLayout的使用非常方便,具体的使用如下所示:
1,drawerLayout 其实就是一个布局控件,跟RelativeLayout差不多,单是drawerLayout是带有侧滑效果的控件。drawerLayout布局里面可以包含两个布局,主内容布局和侧滑布局。
其中主内容布局要写在侧滑布局的前面。
<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/id_drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.example.mgsd.myapplication.MainActivity"
tools:showIn="@layout/activity_main">
<-- 主内容布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_dark">
<ImageView
android:id="@+id/iv_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
</LinearLayout>
<-- 侧滑布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@android:color/holo_red_dark">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundGravity="left"></ListView>
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
注:在侧滑菜单的布局部分,一定要设置android:layout_gravity属性,来设置菜单是从左侧还是右侧滑出,一般设置android:layout_gravity=”start”属性,从左侧滑出。
2,drawerLayout菜单的展开和隐藏可以被DrawerLayout.DrawerListener监听到,所以可以再打开和关闭的时候完成自己的逻辑,但是如果你还是用Toolbar,建议使用
ActionBarDrawerToggle 来监听侧滑菜单的打开和关闭,ActionBarDrawerToggle实现了DrawerListener,所以他能做DrawerListener可以做的任何事情,同时他还能将drawerLayout的展开和隐藏与actionbar的app 图标关联起来,当展开与隐藏的时候图标有一定的动画效果,点击图标的时候还能展开或者隐藏菜单。
mDrawerToggle = new ActionBarDrawerToggle(this,
drawerLayout,
toolbar,
R.string.drawopen,
R.string.drawclose) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
toolbar.setTitle("侧滑栏");//弹出菜单修改toolbar的title
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
toolbar.setTitle("APP FrameWork");
}
};
mDrawerToggle.syncState();
drawerLayout.setDrawerListener(mDrawerToggle);
3,侧滑菜单内容。
侧滑菜单里面可以是任何形式,完全自己设置,例如,上面的布局中我们设置了listview,那样我们就可以在侧滑菜单中展示listview或者更简单的布局,像是展示图片,文字等。也可以在侧滑菜单中加载Fragment,然后操作fragment,如下所示:
" data-snippet-id="ext.e870f61ead632da539051434e7a5fada" data-snippet-saved="false" data-codota-status="done"><LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@android:color/holo_red_dark">
<FrameLayout
android:id="@+id/framlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundGravity="left"></FrameLayout>
</LinearLayout>
然后创建一个Fragment,使用getSupportFragmentManager().beginTransaction().add(R.id.framlayout, new Fragment()).commit();将Fragment添加到侧滑菜单中。
4,主动展开和隐藏菜单栏的方法:
DrawerLayout.closeDrawer方法用于隐藏侧边菜单,DrawerLayout.openDrawer方法用于展开侧边菜单
5.如何在菜单展开或者隐藏的时候更新activity的menu
上面的的第2点讲到DrawerLayout.DrawerListener监听展开与隐藏事件,在监听的回调方法中我们用invalidateOptionsMenu通知activity重绘menu,然后activity就有机会在onPrepareOptionsMenu方法中更新menu元素的显示与隐藏
代码:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
6.如何让app图标点击的时候能够展开或者隐藏侧边菜单。
一般的想法是在activity的onOptionsItemSelected方法中判断点击事件是否来自于app图标,然后用DrawerLayout.closeDrawer和DrawerLayout.openDrawer来隐藏与展开(参见第4点:在代码中主动展开与隐藏侧边菜单)。但是drawerLayout提供了更优雅的方式:使用ActionBarDrawerToggle的onOptionsItemSelected方法。该方法activity的onOptionsItemSelected方法中根据传递进来的menu item做了上面我们在“一般想法”中提到的事情。用官方的说法是”ActionBarDrawerTogglewill take care of this”。我们只需这样做就ok了:
Activity中:
@Override
public booleanonOptionsItemSelected(MenuItem item) {
// The action bar home/up actionshould open or close the drawer.
// ActionBarDrawerToggle will takecare of this.
if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
……….//处理其他菜单点击事件
returnsuper.onOptionsItemSelected(item);
}
注:如果不仔细阅读官方文档,估计我们很难看出(mDrawerToggle.onOptionsItemSelected(item)在这里的作用,这也是我刚开始最疑惑的地方。
补充:
补充一些东西:前几天做主题切换,发现结合Toobar和 DrawerLayout使用在左上角会自动生成一个三个横杠的图标,由于项目需求,我需要将其改为自定义图标:然后我查看了ActionBarDrawerToggle的源码发现:
public void setDrawerIndicatorEnabled(boolean enable) {
if (enable != mDrawerIndicatorEnabled) {
if (enable) {
setActionBarUpIndicator((Drawable) mSlider,
mDrawerLayout.isDrawerOpen(GravityCompat.START) ?
mCloseDrawerContentDescRes : mOpenDrawerContentDescRes);
} else {
setActionBarUpIndicator(mHomeAsUpIndicator, 0);
}
mDrawerIndicatorEnabled = enable;
}
}
看上面的意思是 使用或者禁止使用系统图标。
然后也就是说enable是true的时候会走系统的逻辑,展示的是系统图标,这就是很多人为什么设置actionbar的setHomeAsUpIndicator也不好使的原因,所以我们需要两步:
mDrawerToggle.setDrawerIndicatorEnabled(false);//设置为false时显示自己设置的图标
actionBar.setHomeAsUpIndicator(//自己的图标);
然后这个时候因为屏蔽了系统操作,所以此时点击图标是不会滑出侧滑栏的,我们需要自己添加点击侧滑功能:
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
openDrawerLayout();
}
});
这样我们就更换了图标