Android 基础之侧滑菜单的使用

相信很多朋友都见过可以侧滑的Android应用,比如QQ,知乎,谷歌音乐,CSDN等。这个现在几乎所有流行应用都在使用,今天看看这个是怎么实现的.

DrawerLayout

drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产物。drawerLayout分为侧边菜单和主内容区两部分,侧边菜单可以根据手势展开与隐藏(drawerLayout自身特性),主内容区的内容可以随着菜单的点击而变化(这需要使用者自己实现)。

DrawerLayout的使用:

  1. 直接将DrawerLayout作为根布局,然后其内部第一个View为内容区域,第二个View为左侧菜单,第三个View为右侧侧滑菜单,当前第三个是可选的。
  2. 第一个View的宽高应当设置为match_parent。
  3. 第二、三个View需要设置android:layout_gravity=”left”,和android:layout_gravity=”right”且一搬高度设置为match_parent,宽度为固定值,即侧滑菜单的宽度。

main.XML代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#004FFF"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<!--第一个子元素是抽屉没有打开时显示的布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<ImageView
android:id="@+id/iv_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />

<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:gravity="center"
android:text="消息"
android:textSize="20sp" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!--第二个子元素是抽屉中的内容,即抽屉布局 -->
<LinearLayout
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#004FFF"
android:orientation="vertical" >

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center"
android:padding="10dp"
android:text="子菜单一"
android:textSize="20sp" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>

DrawerLayout常用的一些方法:

  1. 关闭抽屉: drawerlayout.closeDrawers();
  2. 打开抽屉:drawerlayout.openDrawer(抽屉view);
  3. 设置抽屉的阴影:setDrawerShadow(@DrawableRes int resId, @EdgeGravity int gravity) 如果你的抽屉在左边的话设置成 Gravity.LEFT显示.反之.

main.XML代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.example.drawerLayout;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MainActivity extends Activity implements OnClickListener {
DrawerLayout drawerLayout;
ImageView iv_click;
LinearLayout ll;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().hide();
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
iv_click = (ImageView) findViewById(R.id.iv_click);
ll = (LinearLayout) findViewById(R.id.ll);

iv_click.setOnClickListener(this);
//将侧滑菜单设置为屏幕的三分之二
LayoutParams layoutParams = ll.getLayoutParams();
layoutParams.width = getResources().getDisplayMetrics().widthPixels * 2 / 3;
ll.setLayoutParams(layoutParams);

}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.iv_click:
//监听 打开抽屉
drawerLayout.openDrawer(Gravity.LEFT);
break;

default:
break;
}
}
}

SlidingMenu

drawerLayout是Support Library包中实现了侧滑菜单效果的侧滑菜单栏,github上有个应用非常广泛的开源库SlidingMenu。很多著名的应用都用了这个开源库。

开源库地址: SlidingMenu

SlidingMenu是一个开源库,而不是一个完整的项目,要把它作为libary引入到你自己的工程里,简单配置一下就可以实现SlidingMenu的效果。

SlidingMenu的使用:

一、新建一个Android项目,将SlidingMenuLibrary导入新建的Android项目中,步骤如下:
1、 右键点击新建的Android项目,然后点击最下方的“Properties”选项;
2、 点击弹出对话框之后,在最左侧选择“Android”选项,然后再点击右下方的“Add”按钮;
3、 点击后弹出对话框,选中之前导入的SlidingMenuLibrary项目;
4、 导入成功之后会在Android的引用包中出现一个slidingmenulibrary.jar包;

注意:
有个地方需要特别注意:在新建完Android项目之后,较新的Eclipse版本都会在Android目录下 生成一个libs的文件夹,里面会有一个android-support-v4.jar的jar包,这个jar一定要删掉,否则运行程序的时候会出现异常,提示是找不到类的异常。最后发现出现异常的原因是因为在导入slidingmenulibrary类库的时候,这个类库里面本身就包含了android-support-v4.jar的jar包,所以运行的时候就会出现异常,系统不知道去调用哪个路径的下的包,所以程序崩溃,提示找不到类。
二、使用SlidingMenu开源库开发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.sildingmenu;

import android.app.Activity;
import android.os.Bundle;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;

public class MainActivity extends Activity {

private SlidingMenu slidMenu;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
slidMenu = new SlidingMenu(this);
slidMenu.setMode(SlidingMenu.LEFT);
slidMenu.setMenu(R.layout.asdf);
slidMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);
slidMenu.setTouchModeBehind(SlidingMenu.TOUCHMODE_MARGIN);
slidMenu.setBehindWidth(300);
slidMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
}
}

SlidingMenu常用的一些方法:

方法名称 介绍
slidMenu.setShadowWidth(10); 设置阴影图片的宽度
slidMenu.setShadowWidth(10); 设置阴影图片
menu.toggle(); 动态判断自动关闭或开启SlidingMenu
menu.showMenu(); 显示SlidingMenu
menu.showContent(); 显示内容
menu.setOnOpenListener(onOpenListener); 监听slidingmenu打开
menu.OnCloseListener(OnCloseListener); 监听slidingmenu关闭时事件
menu.OnClosedListener(OnClosedListener); 监听slidingmenu关闭后事件

Android Design Support Library 给开发者带来了一些重要的 Material Design 组件,并且向下兼容到 Android 2.1, NavigationView 就是其中之一,可用于方便地创建导航抽屉。

NavigationView 在很多App上都已经可以看到其效果图,国内的比如知乎(侧拉菜单滑出来的那一部分属于NavigationView),还有Google自己的那些app,也基本全都采用了NavigationView。

NavigationView

  1. NavigationView 要放在一个 DrawerLayout 中,并且充当第二个子元素作为抽屉中的内容,即抽屉布局。android:layout_gravity=”start”是让NavigationView收进左侧。
  2. 在NavigationView中,必须规定app:headerLayout=”@layout/nav_header”、app:menu=”@menu/navigationdrawer_main”,其中的nav_header.xml和navigationdrawer_main.xml 指头部布局和菜单项,navigationdrawer_main.xml 中group与group之间会有横线。
  3. 在activity中初始化 DrawerLayout ,NavigationView ,然后实现点击头部事件,条目点击事件,在有toolbar的情况下,设置点击toolbar的navigationIcon打开NavigationView侧边栏。

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">

<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<android.support.design.widget.NavigationView
android:id="@+id/navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@android:color/white"
app:headerLayout="@layout/nav_header"
app:menu="@menu/navigationdrawer_main" />

</android.support.v4.widget.DrawerLayout>

nav_header.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<ImageView
android:id="@+id/iv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="@mipmap/material_design_feature" />

<TextView
android:id="@+id/tv_tologin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|left"
android:layout_margin="16dp"
android:text="点击进入登录界面"
android:textColor="@color/white" />
</FrameLayout>

navigationdrawer_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/g1">

<item
android:id="@+id/show_recyclerview"
android:icon="@mipmap/lists"
android:title="RecyclerView" />
<item
android:id="@+id/show_fullscreen"
android:icon="@mipmap/fulling"
android:title="全屏" />
<item
android:id="@+id/show_floating"
android:icon="@mipmap/floating"
android:title="悬浮球(窗)" />
<item
android:id="@+id/show_animation"
android:icon="@mipmap/animation"
android:title="动画" />
<item
android:id="@+id/show_navigationview"
android:icon="@mipmap/navigations"
android:title="底部导航栏" />
</group>
<group android:id="@+id/g2">
<item
android:id="@+id/show_setting"
android:icon="@mipmap/setting"
android:title="设置" />
<item
android:id="@+id/show_about"
android:icon="@mipmap/about"
android:title="关于" />
<item
android:id="@+id/XXX"
android:icon="@mipmap/ic_launcher"
android:title="XX" />
</group>
<item android:title="二级菜单测试">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@mipmap/ic_launcher"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@mipmap/ic_launcher"
android:title="Send" />
</menu>
</item>
</menu>

MainActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class MainActivity extends AppCompatActivity implements View.OnClickListener, NavigationView.OnNavigationItemSelectedListener {
NavigationView navigationview;
DrawerLayout mDrawerLayout;
Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置点击toolbar的navigationIcon打开NavigationView侧边栏
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDrawerLayout.openDrawer(mNavigationView);
}
});
//5.0以上设置状态栏透明
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
navigationview = (NavigationView) findViewById(R.id.navigationview);
navigationview.setItemIconTintList(null);//设置NavigationView的菜单图标背景色,否则显示灰色
//设置toolbar图标与抽屉导航之间的交互
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawerlayout, tb_toolbar_main, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawerlayout.addDrawerListener(toggle);
toggle.syncState();
//抽屉菜单项点击事件
navigationview.setNavigationItemSelectedListener(this);
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.show_about:
// Toast.makeText(MainActivity.this, "about", Toast.LENGTH_SHORT).show();
intent = new Intent(MainActivity.this, AboutActivity.class);
startActivity(intent);
break;
}

//先清除所有,重新加载后,在选中要选的。配合fragment使用效果更佳
navigationview.getMenu().clear();
navigationview.inflateMenu(R.menu.navigationdrawer_main);
//设置选中项目
navigationview.getMenu().findItem(item.getItemId()).setChecked(true);
//点击后自动关闭抽屉
drawerlayout.closeDrawer(Gravity.START);
return true;
}
}
  1. NavigationView放置在Toolbar下方
  2. ss

NavigationView在Toolbar下方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/sample_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:theme="@style/ThemeOverlay.AppCompat.Dark" />

<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<TextView
android:padding="16dp"
android:text="NavigationView在Toolbar下方"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

<android.support.design.widget.NavigationView
android: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"
app:menu="@menu/navigationdrawer_main"/>

</android.support.v4.widget.DrawerLayout>
</LinearLayout>