Android 笔记 —— 侧滑菜单(抽屉)

侧滑菜单这种设计,在很多 APP 上面都有看到,例如大版本3.0之前的知乎、网易新闻、滴滴打车等。有些热衷于 Android Material Design 的开发者,甚至将一些 IOS 化的 Android 应用改头换面,将其 MD 化。这过程中,基本上都会给这些“改版”应用装上“抽屉”,例如 Xposed 上面的经典插件——“WechatUI ”、Github 上面的“Material Design 豆瓣客户端——豆芽”,以及一些第三方微博客户端。
既然侧滑菜单如此受大家欢迎,那我们就赶紧去了解一下它吧

侧滑菜单的实现方式

侧滑菜单主要有两种实现方式,一是使用开源库,如 SlidingMenuMaterialDrawer 等,二是使用 Android 官方推荐的 DrawerLayout 实现。
我们就先以官方推荐的为基础来进行学习,如果能把官方推荐的知识掌握了,再使用开源库就更不是问题了。

DrawerLayout

DrawerLayout 是谷歌推出的一款用于实现侧滑菜单效果的控件,集成在 support library 里面,使用时需要加载 android-support-v4.jar 包。
DrawerLayout 分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开或隐藏,主内容区可以根据侧边菜单的变换而改变。

使用方法

先看代码

布局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:id="@+id/activity_main"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.ginkwang.drawertest.MainActivity">
​
   <FrameLayout
       android:id="@+id/fl_content"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>
​
   <!--左边抽屉菜单-->
   <RelativeLayout
       android:id="@+id/rl_left"
       android:layout_width="200dp"
       android:layout_height="match_parent"
       android:layout_gravity="left"
       >
       <ListView
           android:id="@+id/lv_left"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
   </RelativeLayout>
​
   <!--右边抽屉菜单-->
   <RelativeLayout
       android:id="@+id/rl_right"
       android:layout_width="200dp"
       android:layout_height="match_parent"
       android:layout_gravity="right"
       >
       <ListView
           android:id="@+id/lv_right"
           android:layout_width="match_parent"
           android:layout_height="match_parent"/>
   </RelativeLayout>
</android.support.v4.widget.DrawerLayout>

从布局文件可以看出,DrawerLayout 是根布局,然后紧跟着的是第一个子元素是默认内容(抽屉未打开的默认内容,即本例中的 FrameLayout),之后的是抽屉内容。
抽屉菜单的摆放通过抽屉布局的 android:layout_gravity="" 的属性来控制,可填入 "left"、"right"、"start"、"end"。此属性必须设置,要不然侧滑抽屉时会报错。
抽屉菜单宽度单位为 dp,大小一般不超过 320dp,这样打开抽屉后,依然可以看到部分内容布局。

代码

布局文件写好之后,侧滑效果按理说就已经实现了。但是此时你滑动菜单时,会发现左边拉出来什么内容都没有,这是因为我们没有给菜单布局注入数据。

public class MainActivity extends AppCompatActivity {
​
   private static final String TAG = "MainActivity";
​
   private Context mContext;
   private DrawerLayout mDlMain;
   private FrameLayout mFlContent;
   private RelativeLayout mRlLeft, mRlRight;
   private ListView mLvLeft;
   private TextView mTvRight;
​
   private String[] leftMenuNames = {"left_item1", "left_item2",
           "left_item3", "left_item4"};
​
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mContext = this;
       initView();
   }
​
   private void initView() {
       mDlMain = (DrawerLayout) findViewById(R.id.dl_main);
       mFlContent = (FrameLayout) findViewById(R.id.fl_content);
       mRlLeft = (RelativeLayout) findViewById(R.id.rl_left);
       mRlRight = (RelativeLayout) findViewById(R.id.rl_right);
       mLvLeft = (ListView) findViewById(R.id.lv_left);
       mLvLeft.setAdapter(new ArrayAdapter<String>(mContext,
               android.R.layout.simple_list_item_1, leftMenuNames));//给左边菜单写入数据
       mTvRight = (TextView) findViewById(R.id.tv_right);
       mTvRight.setText("right_content");//给右边菜单内容赋值
   }
}

效果

左边菜单
右边菜单

菜单添加点击事件

菜单做好之后,自然就会给菜单赋予点击事件,来控制主内容区显示的内容。给菜单添加点击事件,其实就是给菜单布局里面的 listview 添加点击事件。这个简单得很,就是 listview.setOnItemClickListener(this) 即可。点击之后,我们之前在主界面布局里定义的 FrameLayout 就会显示相应的 Fragment。代码如下:

mLvLeft.setOnItemClickListener(this);
​
...
​
//左侧菜单点击事件
   @Override
   public void onItemClick(AdapterView<?> pAdapterView, View pView, int pI, long pL) {
       Fragment lFragment = new MenuFragment();
       Bundle lBundle = new Bundle();
       lBundle.putString("menu_str", "item_" + (pI + 1));
       lFragment.setArguments(lBundle);
       FragmentManager fragmentManager = getFragmentManager();
       fragmentManager.beginTransaction().replace(R.id.fl_content, lFragment).commit();
       mLvLeft.setItemChecked(pI, true);
       mDlMain.closeDrawers();//关闭抽屉
   }

MenuFragment 代码如下:

public class MenuFragment extends Fragment {
​
   private View mView;
   private Context mContext;
   private TextView mTvMenuFragment;
​
   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       mView = inflater.inflate(R.layout.layout_fragment_menu, container, false);
       mContext = getActivity();
       Bundle lBundle = getArguments();
       mTvMenuFragment = (TextView) mView.findViewById(R.id.tv_menu_fragment);
       if (lBundle != null) {
           mTvMenuFragment.setText(lBundle.getString("menu_str"));
       }
       return mView;
   }
}

上面代码中,涉及到一个关闭抽屉的操作 DrawerLayout .closeDrawers(),那打开抽屉的操作就是 DrawerLayout .openDrawer(int gravity),gravity 为抽屉开启方向,应与布局文件中定义的方向一致,不然会报错。下面在代码中实现按钮控制抽屉的开启操作:

布局:

在默认显示布局的 FrameLayout 中添加操作按钮:

<FrameLayout
       android:id="@+id/fl_content"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
       <Button
           android:id="@+id/btn_open_left_drawer"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="开启左边抽屉"/>
​
       <Button
           android:id="@+id/btn_open_all_drawer"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="center|top"
           android:text="开启全部抽屉"/>
​
       <Button
           android:id="@+id/btn_open_right_drawer"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_gravity="right"
           android:text="开启右边抽屉"/>
   </FrameLayout>
代码:

在代码中初始化按钮,并实现按钮点击事件:

private Button mBtnOpenLeftDrawer, mBtnOpenAllDrawer, mBtnOpenRightDrawer;
​
...
 
mBtnOpenLeftDrawer = (Button) findViewById(R.id.btn_open_left_drawer);
       mBtnOpenLeftDrawer.setOnClickListener(this);
       mBtnOpenAllDrawer = (Button) findViewById(R.id.btn_open_all_drawer);
       mBtnOpenAllDrawer.setOnClickListener(this);
       mBtnOpenRightDrawer = (Button) findViewById(R.id.btn_open_right_drawer);
       mBtnOpenRightDrawer.setOnClickListener(this);
​
...
​
@Override
   public void onClick(View pView) {
       switch (pView.getId()) {
           case R.id.btn_open_left_drawer:
               mDlMain.openDrawer(Gravity.LEFT);
               break;
​
           case R.id.btn_open_all_drawer:
               mDlMain.openDrawer(Gravity.LEFT);
               mDlMain.openDrawer(Gravity.RIGHT);
               break;
​
           case R.id.btn_open_right_drawer:
               mDlMain.openDrawer(Gravity.RIGHT);
               break;
       }
   }

效果:

按钮控制侧滑菜单

去除抽屉划出后主内容页背景的灰色

DrawerLayout.setScrimColor(Color.TRANSPARENT);

填充抽屉划出后与屏幕边缘之间的内容

DrawerLayout.setDrawerShadow();

常见问题

  • 在点击DrawerLayout中的空白处的时候,底部的content会获得事件
    由于Google的demo是一个ListView,所以ListView会获得焦点,事件就不会传递了,看不出来问题。但是如果用的include加载的布局,会出现这个情况,那么如何解决?
    解决办法:在include进的那个布局里面,添加clickable=true
  • 除了抽屉的布局视图之外的视图究竟放哪里
    左、右抽屉和中间内容视图默认是不显示的,其他布局视图都会直接显示出来,但是需要将其放在 DrawerLayout 内部才能正常使用(不要放在外面),否则要么是相互覆盖,或者就是触屏事件失效,滚动等效果全部失效。

使用 NavigationView 实现侧滑菜单的布局

前文中涉及到的侧滑菜单的布局都是我们自己写的,虽然逻辑并不复杂,各种样式也可定义无限制,但总是要耗费些许时间。而且各家 APP 最终实现的样式也五花八门,风格不统一。
终于,谷歌在 Android 大版本5.0时推出了 MD 风格的导航菜单 —— NavigationView 。NavigationView 整体分为两部分,上部分叫 HeaderLayout,下部分的点击项为 Menu。
我们就一起来看看 NavigationView 的使用方式吧。

NavigationView 使用方法

NavigationView 是 Design Support 中的控件,所以如果想要使用它,首先要先引入 Design 库。

引入 Design 库

在项目的 build.gradle 中添加如下代码:

dependencies {
 
   ...
     
   compile 'com.android.support:design:26.0.0-alpha1'
}

然后我们还要准备好构成 NavigationView 的两个部分,Menu 和 HeaderLayout。

新建 Menu

在 xml 下新建 menu 文件夹,然后在 menu 文件夹下再新建 nav_manu.xml 文件,menu 文件代码为:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <group android:checkableBehavior="single">
       <item
           android:id="@+id/item_nav_menu_news"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_news"/>
​
       <item
           android:id="@+id/item_nav_menu_star"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_star"/>
​
       <item
           android:id="@+id/item_nav_menu_share"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_share"/>
​
       <item
           android:id="@+id/item_nav_menu_set"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_set"/>
   </group>
</menu>

可以看到,menu 文件夹下是一个 group 组,其中 android:checkableBehavior 属性设置为 single,代表 menu 项为单选。
然后每个菜单项是由一个个的 item 构成的,item 的几个属性的简单易懂,这里就不详述。

新建 HeaderLayout

在 xml 下的 layout 文件夹中新建 layout_nav_header.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="200dp"
             android:background="?attr/colorPrimary"
             android:gravity="center"
             android:orientation="vertical"
             android:padding="15dp">
​
   <ImageView
       android:id="@+id/iv_nav_img"
       android:layout_width="50dp"
       android:layout_height="50dp"
       android:src="@mipmap/ic_launcher"/>
​
   <TextView
       android:id="@+id/tv_nav_txt"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginTop="15dp"
       android:text="我知道你 的忧郁是为了什么"
       android:textColor="@android:color/white"/>
​
</LinearLayout>

这段代码也很好懂,就是定义了一个 ImageView,下面是一行说明文字。
OK,我们正式进入主题,对 NavigationView 进行操作。

使用 Navigationview

此示例还是在前文介绍 DrawerLayout 的项目中运行的,为了不破坏之前的代码,我们新建一个活动,在另一个活动中使用 Navigationview。
新建一个跳转到新活动的按钮,并写好逻辑:

<Button
   android:id="@+id/btn_goto_nav"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center"
   android:text="NavigationView"/>

case R.id.btn_goto_nav:
               startActivity(new Intent(MainActivity.this, NavActivity.class));
               break;

NavActivity 就是我们新建的活动。
然后在这个活动中加入 Navigationview 控件,布局中其他还是和前文一样,只是将我们之前自定义的侧滑菜单换成 Navigationview。

<android.support.v4.widget.DrawerLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:id="@+id/dl_nav"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.ginkwang.drawertest.NavActivity">
​
   <FrameLayout
       android:id="@+id/fl_nav_layout"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       >
       <TextView
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:gravity="center"
           android:text="NavigationView 抽屉菜单"
           android:textColor="@android:color/black"
           android:textSize="25sp"/>
   </FrameLayout>
   
   <android.support.design.widget.NavigationView
       android:id="@+id/nav_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_gravity="start"
       app:menu="@menu/nav_menu"
       app:headerLayout="@layout/layout_nav_header"/>
</android.support.v4.widget.DrawerLayout>

然后在代码中获取到 Navigationview,并设置其 menu 的点击事件:

private NavigationView mNavView;
​
...
 
mNavView = (NavigationView) findViewById(R.id.nav_view);
mNavView.setCheckedItem(R.id.item_nav_menu_news);
mNavView.setNavigationItemSelectedListener(this);
​
...
 
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
   Toast.makeText(NavActivity.this, item.getTitle(), Toast.LENGTH_LONG).show();
   mDlNav.closeDrawers();
   return true;
}

逻辑也十分简单,就是打开抽屉之后,点击某一项 menu,会将抽屉关闭,然后提示你当前操作哪项的吐司。其中

mNavView.setCheckedItem(R.id.item_nav_menu_news);

表示设置 menu 的默认选中状态。

最后效果图:

NavigationView 抽屉菜单

到这里,不知道大家看出一个问题没有,之前我们定义的 menu item 的 icon 是项目中自带的 ic_launcher。它的本身面目是这样的:

ic_launcher.png

但是在效果图中,却显示成了灰色的。
对于这个问题,有两个解决办法:
在 Navigationview 的布局中添加 app:itemIconTint="@color/colorPrimary" 属性,颜色值自定义。

menu颜色1

但是这样设置后,还只是能显示纯色,那如果非要显示原本的图片该怎么设置呢?让我们来看第二个解决方法;

在代码中获取到 Navigationview 后,设置其属性

mNavView.setItemIconTintList(null);
menu 颜色2

NavigationView 添加分割线

有时候,侧滑菜单的 item 太多,需要将其按类划分,设置分割线以及类标注以作明示。
这时,我们只需要将相应的 item 规划在一个 group 内即可。看代码:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <group android:checkableBehavior="single">
       <item
           android:id="@+id/item_nav_menu_news"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_news"/>
​
       <item
           android:id="@+id/item_nav_menu_star"
           android:icon="@mipmap/ic_launcher"
           android:title="@string/nav_menu_star"/>
   </group>
​
   <item android:title="@string/nav_menu_title_common">
       <menu>
           <group android:checkableBehavior="single">
               <item
                   android:id="@+id/item_nav_menu_share"
                   android:icon="@mipmap/ic_launcher"
                   android:title="@string/nav_menu_share"/>
​
               <item
                   android:id="@+id/item_nav_menu_set"
                   android:icon="@mipmap/ic_launcher"
                   android:title="@string/nav_menu_set"/>
           </group>
       </menu>
   </item>
​
   <item android:title="@string/nav_menu_title_other">
       <menu>
           <group android:checkableBehavior="single">
               <item
                   android:id="@+id/item_nav_menu_send"
                   android:icon="@mipmap/ic_launcher"
                   android:title="@string/nav_menu_send"/>
           </group>
       </menu>
   </item>
</menu>

如果只要分割线的话,只需要将 item 放在 group 内即可。如果想要副标题指示的话,就需要将其中的 item 规划在一个新的 item 中,并指定其 title 属性。看效果:

分割线

NavigationView 头布局(HeaderLayout)点击事件

上面代码中已经介绍了 menu 的点击事件,只需要在代码中获取到 menu 菜单,然后重写 onNavigationItemSelected 即可。
头布局的点击事件的获取和 menu 的一样,也是在代码中先获取到头布局的 view,然后调用头布局 view 的 findViewById() 获取头布局里面的控件,然后获取到控件的点击事件,看代码:

private View mHeaderView;
private ImageView mIvHeaderImg;
​
...
​
mHeaderView = mNavView.getHeaderView(0);//获取头布局
mIvHeaderImg = (ImageView) mHeaderView.findViewById(R.id.iv_nav_img);//获取头布局内 imageview 控件
mIvHeaderImg.setOnClickListener(this);
​
...
​
@Override
public void onClick(View pView) {
   Toast.makeText(NavActivity.this, "点击 ImageView", Toast.LENGTH_LONG).show();
}

整体逻辑也十分简单,就是其中获取头布局的代码 getHeaderView(0) ,可能会有人不理解。
其实 Navigationview 本质上是一个 RecyclerView,头布局通常是第一个元素,所以获取头布局的方式自然是 getHeaderView(0)。

注意

如果你的 buildToolsVersion 版本是 23.1.0,那获取头布局的代码为:

View headerLayout =
navigationView.inflateHeaderView(R.layout.navigation_header);

参考:

NavigationView获取Header View的问题

结合 ToolBar,一同构建侧滑菜单

写到这里,滑动菜单的实现的大部分知识点都已经涵盖在内了,但是还有一个问题,就是前文中的例子滑动菜单的出现都是我们用手滑动屏幕边缘才出来的(废话!所以叫滑动菜单啊!)。我的意思是,即诶岸上没有一个提示功能让人知道滑动菜单的存在。Material Design 的建议是在 Toolbar 的左边添加一个导航按钮,点击按钮抽屉就会出现。这相当于给用户两种打开抽屉的方式,防止一些用户不知道抽屉的存在。
接下来我们就来实现这个功能。

添加 Toolbar

我们还是在 NavigationView 的示例项目中操作,还不了解 Toolbar 的朋友请先看一下这篇文章 Android 笔记 —— Toolbar 使用总结,布局中添加 Toolbar 的代码就不贴了,直接看 Activity 中修改的逻辑。

mToolbar = (Toolbar) findViewById(R.id.tb_nav_bar);
setSupportActionBar(mToolbar);//添加 Toolbar
​
...
​
ActionBar lActionBar = getSupportActionBar();
if (lActionBar != null) {
   lActionBar.setDisplayHomeAsUpEnabled(true);//显示返回按钮
   lActionBar.setHomeAsUpIndicator(R.mipmap.ic_toolbar_menu);//替换返回按钮图标,改为导航按钮
}
​
...
​
@Override
public boolean onOptionsItemSelected(MenuItem item) {
   switch (item.getItemId()) {
       case android.R.id.home:
           mDlNav.openDrawer(Gravity.START);
           break;
   }
   return true;
}

我们先是将 Toolbar 添加进来并获取,然后通过 getSupportActionBar() 获取到 ActionBar,这里 ActionBar 的具体实现是由 Toolbar 来完成的。
之后通过 ActionBar.setDisplayHomeAsUpEnabled(true) 显示 Toolbar 的返回按钮,再替换但会按钮的图标样式,改为导航图标。
这时,你点击导航按钮的话,菜单还是不会出现,而是返回到上一个活动,本质上它现在还是一个返回按钮。
接着我们再替换它的功能,通过重写 onOptionsItemSelected 方法,根据 item 的 id 获取到返回按钮并对其进行处理,HomeAsUp 的按钮 id 是 android.R.id.home。
到此,我们就完成了 Toolbar 添加导航按钮进行抽屉打开的操作了。看一下效果:

Toolbar 导航按钮打开抽屉.gif

抽屉不遮挡 Toolbar

前面我们介绍与演示的都是抽屉拉出后遮挡住 Toolbar 的模式,那相信你也见到或使用过一些 APP ,就是抽屉拉出后,不遮挡 Toolbar,然后 Toolbar 上的导航按钮随着抽屉的拉出状态会变成返回按钮。类似下面这样:


抽屉不遮挡 Toolbar

接下来我们就一起来实现这样的效果吧!
首先,

布局:

<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:orientation="vertical">
​
   <android.support.v7.widget.Toolbar
       android:id="@+id/tb_nav_buttom"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       android:background="?attr/colorPrimary"
       app:theme="@style/ToolbarTheme"/>
​
   <android.support.v4.widget.DrawerLayout
       android:id="@+id/dl_nav_buttom"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
​
       <FrameLayout
           android:layout_width="match_parent"
           android:layout_height="match_parent">
​
           <TextView
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:gravity="center"
               android:text="抽屉不遮挡 Toolbar"
               android:textColor="@android:color/black"
               android:textSize="25sp"/>
       </FrameLayout>
​
       <android.support.design.widget.NavigationView
           android:id="@+id/nv_buttom"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:layout_gravity="start"
           app:headerLayout="@layout/layout_nav_header"
           app:menu="@menu/nav_menu"/>
   </android.support.v4.widget.DrawerLayout>
</LinearLayout>

整个布局的实现逻辑也很简单,就是将 Toolbar 从 DrawerLayout 中隔离出去,放在 DrawerLayout 上面,最外层是一个相对布局,方向是从上至下的。
然后 Toolbar 中有一个设置布局的属性,我们来看一下里面定义了什么:

<style name="ToolbarTheme" parent="AppTheme">
   <!--左边导航按钮颜色-->
   <item name="android:textColorSecondary">@color/colorNav</item>
</style>

只是设置了一个导航按钮的颜色,然后将项目父布局的属性都继承下来。
代码:
来看一下代码中都有什么:

public class NavButtomActivity extends AppCompatActivity {
​
   private DrawerLayout mDlNavButtom;
   private Toolbar mToolbar;
   private ActionBarDrawerToggle mActionBarDrawerToggle;
​
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.layout_nav_buttom_toolbar);
       initView();
   }
​
   private void initView() {
       mToolbar = (Toolbar) findViewById(R.id.tb_nav_buttom);
       mToolbar.setTitle("抽屉不遮挡 Toolbar");//设置标题
       mToolbar.setTitleTextColor(getResources().getColor(R.color.colorText));//标题颜色
       setSupportActionBar(mToolbar);
​
       mDlNavButtom = (DrawerLayout) findViewById(R.id.dl_nav_buttom);
       mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDlNavButtom, mToolbar, 0, 0);
       mDlNavButtom.setDrawerListener(mActionBarDrawerToggle);
       mActionBarDrawerToggle.syncState();//ActionBarDrawerToggle与DrawerLayout的状态同步,
       // 并将ActionBarDrawerToggle中的drawer图标,设置为ActionBar的Home-Button的icon
   }
}

可以看到,我们没有按照前文示例中那样,将 Toolbar 的返回按钮替换为我们自己设置的 icon,而是使用 ActionBarDrawerToggle 的默认图标。
并调用 ActionBarDrawerToggle.syncState() 方法将 ActionBarDrawerToggle 与DrawerLayout 的状态同步,最终实现的效果是这样:

抽屉不遮挡 Toolbar.gif

结束

至此,侧滑菜单(抽屉)的大部分用法已经介绍完了。当然,如果想要在项目中使用抽屉的话,远没有这样复杂,只需要构建工程时选择 Navigation Drawer Activity 即可。另外,Github 上面也有更多功能更强大的关于抽屉的开源库,可供大家选择。

参考

郭霖 《第一行代码》
使用DrawerLayout实现侧拉菜单
android官方侧滑菜单DrawerLayout详解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,322评论 5 465
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,288评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,227评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,015评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,936评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,534评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,995评论 3 389
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,616评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,907评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,923评论 2 315
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,741评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,525评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,016评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,141评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,453评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,054评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,249评论 2 339

推荐阅读更多精彩内容