DrawerLayoutDemo【侧边栏(侧滑菜单)简单实现】
版权声明:本文为HaiyuKing原创文章,转载请注明出处!
前言
简单实现侧边栏(侧滑菜单)效果:
- 点击触发打开左侧侧边栏,手势滑动关闭左侧侧边栏;
- 手势滑动打开右侧侧边栏,手势滑动关闭右侧侧边栏;
- 简单实现打开侧边栏的动画效果(透明度、移动效果);
- 打开侧边栏的时候动态更改侧边栏中的数据;
效果图

代码分析
此Demo只是简单实现侧边栏的效果,目的在于可以快速的导入到项目中。至于更复杂的效果,请阅读《参考资料》
使用步骤
一、项目组织结构图


注意事项:
1、 导入类文件后需要change包名以及重新import R文件路径
2、 Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖
二、导入步骤
引入依赖库
在APP的build.gradle文件中添加以下代码:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.why.project.drawerlayoutdemo"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//DrawerLayout侧边栏中动画效果用到的
compile 'com.nineoldandroids:library:2.4.0'
}
在styles.xml文件中注释和添加以下代码:【主要是用于Demo中的使用自定义的顶部导航栏效果】
<resources>
<!-- Base application theme. -->
<!--<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!– Customize your theme here. –>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>-->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
三、使用方法
在Activity布局文件中使用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/id_drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"> <!-- 主内容视图一定要是DrawerLayout的第一个子视图【必须】 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <!-- 引入导航栏 -->
<include
android:id="@+id/main_navbar"
layout="@layout/navigationbar_main" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="内容区域"
android:textSize="22sp"
android:layout_gravity="center"/> </LinearLayout> <!-- 左侧区域侧边栏【可选】【如果想要只有一个右侧的侧边栏,那么就只需要留一个即可,注意的是left需要换成right】 -->
<!-- android:tag="LEFT"用于java代码中通过drawerView.getTag()判断左侧还是右侧 -->
<fragment
android:id="@+id/fragment_leftmenu"
android:name="com.why.project.drawerlayoutdemo.MainMenuLeftFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:tag="LEFT" /> <!-- 右侧区域侧边栏【可选】 -->
<fragment
android:id="@+id/fragment_rightmenu"
android:name="com.why.project.drawerlayoutdemo.MainMenuRightFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:tag="Right" /> </android.support.v4.widget.DrawerLayout>
顶部菜单栏布局文件navigationbar_main.xml【布局较简单,就不展开了】
<?xml version="1.0" encoding="utf-8"?>
<!-- 首页界面的导航栏布局文件 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_twoversion_home"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_gravity="center"
android:background="#3F51B5" > <!-- 用户侧边栏图标 -->
<ImageView
android:id="@+id/nav_user"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:contentDescription="@string/app_name"
android:gravity="center"
android:src="@drawable/nav_user" /> <!-- 标题 -->
<TextView
android:id="@+id/nav_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:text="@string/app_name"
android:textColor="#ffffff"
android:textSize="18sp" /> </RelativeLayout>
navigationbar_main.xml
创建侧边栏碎片文件——MainMenuLeftFragment、MainMenuRightFragment【根据项目实际需求,可能只需要创建一个即可】【可参考demo中,直接复制到实际项目中,注意修改activity布局文件中的fragment的完整路径地址】

MainMenuLeftFragment.java
package com.why.project.drawerlayoutdemo; import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView; /**
* Created by HaiyuKing
* Used 首页左侧侧边栏碎片界面
*/ public class MainMenuLeftFragment extends Fragment {
private static final String TAG = "MainMenuLeftFragment";
/**View实例*/
private View myView;
//
private TextView tv_show; //重写
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG,"onCreateView");
myView = inflater.inflate(R.layout.fragment_home_left_menu, container, false); return myView;
} @Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Log.d(TAG,"onActivityCreated");
//初始化控件以及设置
initView();
} @Override
public void onResume() {
super.onResume();
Log.d(TAG,"onResume");
//初始化监听事件
initEvent();
} /**初始化控件*/
private void initView(){
Log.d(TAG,"initView");
tv_show = myView.findViewById(R.id.tv_show);
} /**初始化默认数据【这个需要在activity中执行,原因是:在布局文件中通过<fragment>的方式引用Fragment,打开Activity的时候,Fragment的生命周期函数均执行了】
* 那么就存在一个问题,初始化fragment中的数据,可能会在activity数据初始化之前执行*/
public void setDefaultDatas(){
tv_show.setText(tv_show.getText() + "\n执行了一次setDefaultDatas()");
} /**初始化监听事件*/
private void initEvent(){ }
}
fragment_home_left_menu.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<!-- 首页界面的左侧侧边栏界面布局文件 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#E3E3E3">
<TextView
android:id="@+id/tv_show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左侧侧边栏区域"
android:textSize="18sp"
/>
</LinearLayout>
在Activity中使用如下【继承FragmentActivity或者其子类AppCompatActivity】
package com.why.project.drawerlayoutdemo; import android.content.Context;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.ImageView; import com.nineoldandroids.view.ViewHelper; public class MainActivity extends AppCompatActivity { private Context mContext; /**导航栏左侧的用户图标*/
private ImageView nav_userImg; /**导航栏左侧的侧边栏的父容器*/
private DrawerLayout mDrawerLayout;
/**导航栏左侧的侧边栏碎片界面*/
private MainMenuLeftFragment leftMenuFragment; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mContext = this;
//初始化控件
initViews();
//初始化数据
initData();
//初始化控件的点击事件
initEvent();
} private void initViews() {
nav_userImg = (ImageView) findViewById(R.id.nav_user);
mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawerLayout);
//关闭手势滑动:DrawerLayout.LOCK_MODE_LOCKED_CLOSED(Gravity.LEFT:代表左侧的)
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT); leftMenuFragment = (MainMenuLeftFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_leftmenu);
} private void initData() { } private void initEvent() {
//用户图标的点击事件
nav_userImg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OpenLeftMenu();
}
}); //侧边栏的事件监听
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener()
{
/**
* 当抽屉滑动状态改变的时候被调用
* 状态值是STATE_IDLE(闲置-0),STATE_DRAGGING(拖拽-1),STATE_SETTLING(固定-2)中之一。
*/
@Override
public void onDrawerStateChanged(int newState)
{
}
/**
* 当抽屉被滑动的时候调用此方法
* slideOffset 表示 滑动的幅度(0-1)
*/
@Override
public void onDrawerSlide(View drawerView, float slideOffset)
{
Log.w("onDrawerSlide", "slideOffset="+slideOffset);//0.0 -- 0.56 -- 1.0 View mContent = mDrawerLayout.getChildAt(0);//内容区域view
View mMenu = drawerView; float scale = 1 - slideOffset; if (drawerView.getTag().equals("LEFT"))
{//左侧的侧边栏动画效果
//设置左侧区域的透明度0.6f + 0.4f * (0.0 ... 1.0)【也就是打开的时候透明度从0.6f ... 1.0f,关闭的时候反之】
ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * slideOffset);
//移动内容区域:左侧侧边栏宽度 * (0.0 ... 1.0)【也就是打开的时候,内容区域移动从0 ... 左侧侧边栏宽度】
ViewHelper.setTranslationX(mContent,mMenu.getMeasuredWidth() * slideOffset);
mContent.invalidate();//重绘view } else
{//右侧的侧边栏动画效果
//移动内容区域:-右侧侧边栏宽度 * (0.0 ... 1.0)【也就是打开的时候,内容区域移动从-0 ... -左侧侧边栏宽度】
ViewHelper.setTranslationX(mContent,-mMenu.getMeasuredWidth() * slideOffset);
mContent.invalidate();
} }
/**
* 当一个抽屉被完全打开的时候被调用
*/
@Override
public void onDrawerOpened(View drawerView) {
if (drawerView.getTag().equals("LEFT")){//如果感觉显示有延迟的话,可以放到nav_userImg的点击事件监听中执行
leftMenuFragment.setDefaultDatas();//打开的时候初始化默认数据【比如:请求网络,获取数据】
}
}
/**
* 当一个抽屉被完全关闭的时候被调用
*/
@Override
public void onDrawerClosed(View drawerView)
{
//关闭手势滑动:DrawerLayout.LOCK_MODE_LOCKED_CLOSED(Gravity.LEFT:代表左侧的)
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
}
});
} /**打开左侧的侧边栏*/
public void OpenLeftMenu()
{
mDrawerLayout.openDrawer(Gravity.LEFT);
//打开手势滑动:DrawerLayout.LOCK_MODE_UNLOCKED(Gravity.LEFT:代表左侧的)
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,Gravity.LEFT);
}
}
混淆配置
无
参考资料
Android DrawerLayout 高仿QQ5.2双向侧滑菜单
项目demo下载地址
https://github.com/haiyuKing/DrawerLayoutDemo
DrawerLayoutDemo【侧边栏(侧滑菜单)简单实现】的更多相关文章
- Android 侧滑菜单的简单实现(SlidingMenu)二
在上一篇博文中已经简单的实现了侧滑菜单,代码也很简单,就几行代码. 这篇文章依然讲侧滑菜单,与前一篇文章不同的是,这篇文章用不同的代码方式来实现侧滑菜单. 在前面的文章中已经用了在Activity中通 ...
- Android 侧滑菜单的简单实现(SlidingMenu)
在我还没有学习Android的时候就用过侧滑菜单的APP,当时第一个感觉是:哇塞,这效果不错!当然,现在自己都已经学Android了,这效果当然也要做出来啊~ SlidingMenu是一种比较新的设置 ...
- SlidingMenu 侧滑菜单的用法
很多APP都有侧滑菜单的功能,部分APP左右都是侧滑菜单~SlidingMenu 这个开源项目可以很好帮助我们实现侧滑功能,将侧滑菜单引入项目的方式很多中,先通过例子介绍各种引入方式,然后给大家展示个 ...
- Android侧滑菜单代码实现
前两天学习了hyman老师讲的Android侧滑菜单的实现,经过自己的整理分享出来给大家学习一下 现在很多APP都有菜单侧滑的功能,本篇文章主要讲解使用自定义的HorizontalScrollView ...
- Xamarin.Android中使用ResideMenu实现侧滑菜单
上次使用Xamarin.Android实现了一个比较常用的功能PullToRefresh,详情见:Xamarin. Android实现下拉刷新功能 这次将实现另外一个手机App中比较常用的功能:侧滑菜 ...
- Android带侧滑菜单和ToolBar的BaseActivity
写Android的时候,可能有多个界面.在风格统一的软件中,写Activity时会有很多重复.例如我所在软工课程小组的项目:Github链接 ,里面的TaskListActivity和TeacherL ...
- Android DrawerLayout 高仿QQ5.2双向侧滑菜单
1.概述 之前写了一个Android 高仿 QQ5.0 侧滑菜单效果 自定义控件来袭 ,恰逢QQ5.2又加了一个右侧菜单,刚好看了下DrawerLayout,一方面官方的东西,我都比较感兴趣:另一方面 ...
- android 应用架构随笔五(ActionBar与侧滑菜单DrawerLayout)
ActionBar(V7)的添加非常简单,只需要在AndroidManifest.xml中指定Application或Activity的theme是Theme.Holo或其子类就可以了,在Androi ...
- android侧滑菜单笔记
一.SlidingPaneLayout v4包下的控件,使用简单,功能简洁.官方文档明确说明该控件只能左侧滑动.使用如下: <android.support.v4.widget.SlidingP ...
随机推荐
- JUnit 异常处理
java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=testfindAll], {ExactMatcher ...
- Helm学习笔记
Helm学习笔记 Helm 是 Kubernetes 生态系统中的一个软件包管理工具.本文将介绍 Helm 中的相关概念和基本工作原理,并通过一个具体的示例学习如何使用 Helm 打包.分发.安装.升 ...
- MIP 问题解决方案大全(2018-06更新)
在 MIP 推出后,我们收到了一些站长的疑问.现将常见问题整理出来,帮助大家了解 MIP 的知识. 一.MIP 认知类问题 二.改造前准备 三.前端改造,组件使用 四.提交生效 五.MIPCache ...
- 【开源】OSharpNS,轻量级.net core快速开发框架发布
OSharpNS简介 OSharp Framework with .NetStandard2.0(OSharpNS)是OSharp的以.NetStandard2.0为目标框架,在AspNetCore的 ...
- HttpServletRequest 接口、HttpServletResponse 接口、请求转发与重定向
上篇文章我们讲了servlet的基本原理,这章将讲一下剩余的部分. HttpServletRequest 接口 该接口是 ServletRequest 接口的子接口,封装了 HTTP 请求的相关信息, ...
- 从css 3d说到空间坐标轴
有一次我们说到掷骰子那个游戏,当时是用了一个steps属性+雪碧图来制作帧动画,这当然颇为不错,但其实一开始我想的不是这样的,我想的是用真的3d和动画去做,这个方案涉及到不少空间的知识,今天来给大伙好 ...
- Redis - NoSQL数据库技术(一)
NoSQL入门概述(一) 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 什么是NoSQL NoSQL(NoSQL - Not Only SQL),意“不仅仅是SQL”: 泛指非关系 ...
- 【极简版】SpringBoot+SpringData JPA 管理系统
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在上一篇中已经讲解了如何从零搭建一个SpringBo ...
- docker常规操作——启动、停止、重启容器实例
一.启动一个已经停止的容器实例 docker start 容器ID或容器名,建议使用容器ID,容器ID支持模糊查询而容器名称不支持1. 先查看已经暂停的容器实例信息 2. 通过docker start ...
- com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver的区别
com.mysql.jdbc.Driver 是 mysql-connector-java 5中的,com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的 ...