版权声明:本文为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中的使用自定义的顶部导航栏效果】
@color/colorPrimary
@color/colorPrimaryDark
@color/colorAccent
三、使用方法
在Activity布局文件中使用DrawerLayout【注意下面底色标记的代码】
顶部菜单栏布局文件navigationbar_main.xml【布局较简单,就不展开了】
navigationbar_main.xml
创建侧边栏碎片文件——MainMenuLeftFragment、MainMenuRightFragment【根据项目实际需求,可能只需要创建一个即可】【可参考demo中,直接复制到实际项目中,注意修改activity布局文件中的fragment的完整路径地址】
MainMenuLeftFragment.java
packagecom.why.project.drawerlayoutdemo;importandroid.os.Bundle;importandroid.support.v4.app.Fragment;importandroid.util.Log;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.TextView;/*** Created by HaiyuKing
* Used 首页左侧侧边栏碎片界面*/
public class MainMenuLeftFragment extendsFragment {private static final String TAG = "MainMenuLeftFragment";/**View实例*/
privateView myView;// privateTextView tv_show;//重写
publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG,"onCreateView");
myView= inflater.inflate(R.layout.fragment_home_left_menu, container, false);returnmyView;
}
@Overridepublic voidonActivityCreated(Bundle savedInstanceState) {//TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
Log.d(TAG,"onActivityCreated");//初始化控件以及设置
initView();
}
@Overridepublic voidonResume() {super.onResume();
Log.d(TAG,"onResume");//初始化监听事件
initEvent();
}/**初始化控件*/
private voidinitView(){
Log.d(TAG,"initView");
tv_show=myView.findViewById(R.id.tv_show);
}/**初始化默认数据【这个需要在activity中执行,原因是:在布局文件中通过的方式引用Fragment,打开Activity的时候,Fragment的生命周期函数均执行了】
* 那么就存在一个问题,初始化fragment中的数据,可能会在activity数据初始化之前执行*/
publicvoidsetDefaultDatas(){
tv_show.setText(tv_show.getText()+ "\n执行了一次setDefaultDatas()");
}/**初始化监听事件*/
private voidinitEvent(){
}
}
fragment_home_left_menu.xml布局文件
/>
在Activity中使用如下【继承FragmentActivity或者其子类AppCompatActivity】
packagecom.why.project.drawerlayoutdemo;importandroid.content.Context;importandroid.os.Bundle;importandroid.support.v4.widget.DrawerLayout;importandroid.support.v7.app.AppCompatActivity;importandroid.util.Log;importandroid.view.Gravity;importandroid.view.View;importandroid.widget.ImageView;importcom.nineoldandroids.view.ViewHelper;public class MainActivity extendsAppCompatActivity {privateContext mContext;/**导航栏左侧的用户图标*/
privateImageView nav_userImg;/**导航栏左侧的侧边栏的父容器*/
privateDrawerLayout mDrawerLayout;/**导航栏左侧的侧边栏碎片界面*/
privateMainMenuLeftFragment leftMenuFragment;
@Overrideprotected voidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext= this;//初始化控件
initViews();//初始化数据
initData();//初始化控件的点击事件
initEvent();
}private voidinitViews() {
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 voidinitData() {
}private voidinitEvent() {//用户图标的点击事件
nav_userImg.setOnClickListener(newView.OnClickListener() {
@Overridepublic voidonClick(View v) {
OpenLeftMenu();
}
});//侧边栏的事件监听
mDrawerLayout.addDrawerListener(newDrawerLayout.DrawerListener()
{/*** 当抽屉滑动状态改变的时候被调用
* 状态值是STATE_IDLE(闲置-0),STATE_DRAGGING(拖拽-1),STATE_SETTLING(固定-2)中之一。*/@Overridepublic void onDrawerStateChanged(intnewState)
{
}/*** 当抽屉被滑动的时候调用此方法
* slideOffset 表示 滑动的幅度(0-1)*/@Overridepublic void onDrawerSlide(View drawerView, floatslideOffset)
{
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();
}
}/*** 当一个抽屉被完全打开的时候被调用*/@Overridepublic voidonDrawerOpened(View drawerView) {if (drawerView.getTag().equals("LEFT")){//如果感觉显示有延迟的话,可以放到nav_userImg的点击事件监听中执行
leftMenuFragment.setDefaultDatas();//打开的时候初始化默认数据【比如:请求网络,获取数据】}
}/*** 当一个抽屉被完全关闭的时候被调用*/@Overridepublic voidonDrawerClosed(View drawerView)
{//关闭手势滑动:DrawerLayout.LOCK_MODE_LOCKED_CLOSED(Gravity.LEFT:代表左侧的)mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.LEFT);
}
});
}/**打开左侧的侧边栏*/
public voidOpenLeftMenu()
{
mDrawerLayout.openDrawer(Gravity.LEFT);//打开手势滑动:DrawerLayout.LOCK_MODE_UNLOCKED(Gravity.LEFT:代表左侧的)mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,Gravity.LEFT);
}
}
混淆配置
无
参考资料
项目demo下载地址