前言
本篇文章,参考 《第一行代码第2版》
正文
1. 简介
DrawerLayout 是谷歌推荐的一种实现侧滑菜单的控件,是 Meterial Design 中非常常见的效果。
2. 简单用法
2.1 创建项目之后,我们修改 xml 布局如下:
<?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"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:minHeight="?attr/actionBarSize"
android:paddingTop="25dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<!--自定义控件-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center"
android:text="自定义标题"
android:textSize="20dp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
</FrameLayout>
<!-- android:layout_gravity="start" 属性必须指定,left 菜单在左侧,right 菜单在右侧,start
表示跟随系统-->
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#fff"
android:gravity="center"
android:paddingTop="50dp"
android:text="我是菜单栏"
android:textSize="30dp" />
</android.support.v4.widget.DrawerLayout>
最外层是 android.support.v4.widget 包下的 DrawerLayout
接下来是两个子 View ,一个为 FrameLayout ,另一个为 TextView
FrameLayout 中是一个 Toolbar ,注意,FrameLayout 这一层视图不能省,否则 Toolbar 会撑满整个屏幕,就算设置 Toolbar 的高度为固定值也不行。
DrawerLayout 的直接子 View 中的 TextView 就是我们要显示的菜单,当然也可以是其他的布局,因为 DrawerLayout 是继承自 ViewGroup 的,我只是图省事,写了个 Textview,
2.2 Activity 中的代码如下:
package io.github.adsuper.drawerlayouttext;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.WindowManager;
public class MainActivity extends AppCompatActivity {
DrawerLayout drawerlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.setting);
toolbar.setTitle("");
setSupportActionBar(toolbar);
}
注意: Activity 中的代码全都是设置状态栏和 Toolbar 的,与 DrawerLayout 无关,这里贴出来,只是为了美化 Toolbar 而已!
- 对 Toolbar 不太了解的可以参考我这篇博客:Android 之 Toolbar 汇总
2.3 运行之后 ( API 19 手机 ) ,效果图如下所示:
-
菜单栏打开前:
菜单栏打开后:
2.4 优化启动方式
这个菜单栏的启动方式只有一种,只有在贴近屏幕边缘的地方滑动才会出现,为了防止有些用户压根就不知道菜单栏的这种情况,我们增加一种启动方式
看到标题栏左上角的那个导航图标了吧,我们就是要把这个图标和菜单栏联动起来
布局文件不用改变,修改 Activity 中的代码如下:
package io.github.adsuper.drawerlayouttext;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.WindowManager;
public class MainActivity extends AppCompatActivity {
DrawerLayout drawerlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//设置透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
//查找 drawerlayout 控件
drawerlayout = (DrawerLayout) findViewById(R.id.drawerlayout);
toolbar.setNavigationIcon(R.drawable.setting);
toolbar.setTitle("");
setSupportActionBar(toolbar);
}
//重写 onOptionsItemSelected 方法
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
//这个 id 就是标题栏左侧的导航图标的 id 是固定的!
case android.R.id.home:
//使用 openDrawer 打开菜单栏
drawerlayout.openDrawer(GravityCompat.START);
break;
}
return true;
}
}
注意: 查找 drawerlayout 控件时,本人使用了 ButterKnife 8.5.1 版本,却无法把效果显示出来。
- 打开或关闭 DrawerLayout ,执行以下代码:
//关闭
drawerLayout.closeDrawer(GravityCompat.START);
//打开
drawerLayout.openDrawer(GravityCompat.START);
2.5 修改 DrawerLayout 位置
接下来说的是修改 DrawerLayout 上边距的位置,将其放在 Toolbar 的下方
只需要修改布局,改变 DrawerLayout 的布局位置即可,xml 代码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<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/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:minHeight="?attr/actionBarSize"
android:paddingTop="25dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<!--自定义控件-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center"
android:text="自定义标题"
android:textSize="20dp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- android:layout_gravity="start" 属性必须指定,left 菜单在左侧,right 菜单在右侧,start
表示跟随系统-->
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#e98484"
android:gravity="center"
android:paddingTop="50dp"
android:text="我是菜单栏"
android:textSize="30dp" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
-
运行效果如下所示:
3. DrawerLayout 配合 NavigatianView 使用
实际上 DrawerLayout 可以内置任何布局来完善你的侧滑菜单,但是谷歌推荐使用 NavigationView , NavigationView 是 Design Support 库中提供的一个控件,此控件会简化侧滑菜单页面的实现,下边开始使用:
3.1 添加 Design Support 依赖包
// 个人认为,包的版本与 V7 包一致
compile 'com.android.support:design:25.3.1'
3.2 xml 布局中,将原来的 TextView 替换为 NavigationView,如下所示:
<?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"
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<!--自定义控件-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center"
android:text="自定义标题"
android:textSize="20dp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
</FrameLayout>
<!-- android:layout_gravity="start" 属性必须指定,left 菜单在左侧,right 菜单在右侧,start
表示跟随系统-->
<android.support.design.widget.NavigationView
android:id="@+id/navigationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_head_layout"
app:menu="@menu/navigation_menu"></android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
效果如下所示:
注意 NavigationView 中的两条属性
app:headerLayout="@layout/navigation_head_layout"
app:menu="@menu/navigation_menu"
- app:headerLayout 为头布局,即粉色背景部分,navigation_head_layout 的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<!--180dp 是 NavigationView 比较适合的高度-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
android:padding="10dp"
android:background="@color/colorAccent">
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/circle_me"
android:layout_width="70dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:src="@drawable/navigation_me" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textview1"
android:layout_alignParentBottom="true"
android:text="个人博客:https://adsuper.github.io"
android:textSize="16dp"
android:textColor="#fff"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textview2"
android:layout_above="@id/textview1"
android:text="珞璃之神"
android:textSize="16dp"
android:textColor="#fff"
/>
</RelativeLayout>
其中,CircleImageView 是一个第三方的,专门将图片设置为圆形的框架,需要添加依赖:
compile 'de.hdodenhof:circleimageview:2.1.0'
- app:menu 为下方具体的菜单选项,navigation_menu 布局如下:(需要在 menu 文件夹下创建)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- group 标签中的 android:checkableBehavior="single 设置为单选-->
<group android:checkableBehavior="single">
<item
android:id="@+id/mingjiao"
android:icon="@drawable/navigation_icon"
android:title="明教"></item>
<item
android:id="@+id/tianshan"
android:icon="@drawable/navigation_icon"
android:title="天山"></item>
<item
android:id="@+id/gaibang"
android:icon="@drawable/navigation_icon"
android:title="丐帮"></item>
<item
android:id="@+id/murong"
android:icon="@drawable/navigation_icon"
android:title="慕容"></item>
<item
android:id="@+id/xiaoyao"
android:icon="@drawable/navigation_icon"
android:title="逍遥"></item>
<item
android:id="@+id/tianlong"
android:icon="@drawable/navigation_icon"
android:title="天龙"></item>
<item
android:id="@+id/wudang"
android:icon="@drawable/navigation_icon"
android:title="武当"></item>
</group>
</menu>
3.3 activity 中的代码如下:
package io.github.adsuper.drawerlayouttext;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.WindowManager;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
DrawerLayout drawerlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4_2);
//设置透明状态栏
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
drawerlayout = (DrawerLayout) findViewById(R.id.drawerlayout);
NavigationView navigationView = (NavigationView) findViewById(R.id.navigationview);
toolbar.setNavigationIcon(R.drawable.setting);
toolbar.setTitle("");
setSupportActionBar(toolbar);
navigationView.setCheckedItem(R.id.mingjiao);//设置默认选择的 item
//设置 item 的点击事件
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// drawerlayout.closeDrawer(GravityCompat.START);
return true;
}
});
}
/**
* 重写 onOptionsItemSelected 方法,实现标题栏左侧导航按钮打开侧滑菜单
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
drawerlayout.openDrawer(GravityCompat.START);
break;
}
return true;
}
}
3.4 当然也可以改变侧滑菜单的位置,也就是上边距的位置,放在 Toolbar 下,只需要修改布局即可:
<?xml version="1.0" encoding="utf-8"?>
<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/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:minHeight="?attr/actionBarSize"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
<!--自定义控件-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_gravity="center"
android:gravity="center"
android:text="自定义标题"
android:textSize="20dp"
android:textStyle="bold" />
</android.support.v7.widget.Toolbar>
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerlayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.NavigationView
android:id="@+id/navigationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_head_layout"
app:menu="@menu/navigation_menu"
/>
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
显示效果如下:
至此,完结