【移动应用开发技术】自定义Android侧滑菜单控件_第1页
【移动应用开发技术】自定义Android侧滑菜单控件_第2页
【移动应用开发技术】自定义Android侧滑菜单控件_第3页
【移动应用开发技术】自定义Android侧滑菜单控件_第4页
【移动应用开发技术】自定义Android侧滑菜单控件_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】自定义Android侧滑菜单控件

packagecom.tenghu.sideslipmenu.view;importandroid.content.Context;importandroid.os.AsyncTask;importandroid.util.AttributeSet;importandroid.util.DisplayMetrics;importandroid.view.MotionEvent;importandroid.view.VelocityTracker;importandroid.view.View;importandroid.view.WindowManager;importandroid.widget.LinearLayout;/**

*CreatedbyArvin_Lion2014/11/18.

*/publicclassSideslipMenuViewextendsLinearLayout{

//滚动显示和隐藏menu时,手指滑动需要达到的速度

privatestaticfinalintSNAP_VELOCITY=200;

privateViewmMenu;//菜单布局

privateViewmContent;//主内容布局

privateintmScreenWidth;//屏幕宽度

privateintmMenuWidth;//菜单宽度

//menu最多可以滑动到的左边缘,值由menu布局的宽度来定

privateintleftEdge;

//menu最多可以滑到的有边缘,值恒为0

privateintrightEdge=0;

//menu完全显示时,留给content的宽度值

privateinttoRightPaddingWidth=50;

//menu布局的参数,通过此参数来更改leftMargin的值

privateLinearLayout.LayoutParamsmenuParams;

//记录手指按下的横坐标

privatefloatxDown;

//记录手指抬起的横坐标

privatefloatxUp;

//记录手指移动的横坐标

privatefloatxMove;

//当前menu是显示还是隐藏,只有menu完全显示和隐藏才会改变该值,滑动时不会改变

privatebooleanisMenuVisible;

//用于计算手指滑动的速度

privateVelocityTrackermVelocityTracker;

privatebooleanonce;

publicSideslipMenuView(Contextcontext){

super(context);

init(context);

}

publicSideslipMenuView(Contextcontext,AttributeSetattrs){

super(context,attrs);

init(context);

}

/**

*初始化

*/

privatevoidinit(Contextcontext){

//获取WindowManager对象

WindowManagerwindowManager=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);

DisplayMetricsdisplayMetrics=newDisplayMetrics();

windowManager.getDefaultDisplay().getMetrics(displayMetrics);

mScreenWidth=displayMetrics.widthPixels;//获取屏幕宽度

}

@Override

protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){

super.onMeasure(widthMeasureSpec,heightMeasureSpec);

if(!once){

mMenu=getChildAt(0);//获取菜单布局

mContent=getChildAt(1);//获取内容布局

menuParams=(LayoutParams)mMenu.getLayoutParams();//获取菜单参数

mMenuWidth=menuParams.width=mScreenWidth-toRightPaddingWidth;//设置菜单宽度

//左边缘的值赋值为menu宽度的负数

leftEdge=-menuParams.width;

//menu的leftMargin设置为左边缘的值,默认菜单不可见

menuParams.leftMargin=leftEdge;

mContent.getLayoutParams().width=mScreenWidth;//设置内容宽度

once=true;

}

}

@Override

publicbooleanonTouchEvent(MotionEventevent){

createVelocityTracker(event);//创建VelocityTracker对象

switch(event.getAction()){

//手指按下

caseMotionEvent.ACTION_DOWN:

xDown=event.getRawX();//记录横坐标

break;

//手指移动

caseMotionEvent.ACTION_MOVE:

//手指移动时,对比按下的横坐标,计算出移动的距离来调整menu的leftMargin值,从而显示和隐藏menu

xMove=event.getRawX();

//计算获取到距离

intdistanceX=(int)(xMove-xDown);

if(isMenuVisible){

menuParams.leftMargin=distanceX;

}else{

menuParams.leftMargin=leftEdge+distanceX;

}

//如果菜单的左边界小于了可以滑动的左边界

if(menuParams.leftMargin<=leftEdge){

//将可以滑动的左边界赋值给菜单左边界

menuParams.leftMargin=leftEdge;

}elseif(menuParams.leftMargin>=rightEdge){

menuParams.leftMargin=rightEdge;

}

mMenu.setLayoutParams(menuParams);//设置菜单参数

break;

//手指抬起

caseMotionEvent.ACTION_UP:

//手指抬起时,进行判断当前手势的意图,从而决定是滚动到menu界面,还是滚动到content界面

xUp=event.getRawX();

if(wantToShowMenu()){

if(shouldScrollToMenu()){

scrollToMenu();

}else{

scrollToContent();

}

}elseif(wantToShowContent()){

if(shouldScrollToContent()){

scrollToContent();

}else{

scrollToMenu();

}

}

//手指抬起是回收VelocityTracker对象

recycleVelocityTracker();

break;

}

returntrue;

}

/**

*创建VelocityTracker对象,并将触摸content界面的滑动时间加入到VelocityTracker中

*

*@paramevent

*/

privatevoidcreateVelocityTracker(MotionEventevent){

if(null==mVelocityTracker){

mVelocityTracker=VelocityTracker.obtain();//初始化VelocityTracker

}

mVelocityTracker.addMovement(event);//添加界面滑动事件

}

/**

*判断当前手势的意图是不是想显示content,如果手指移动的距离是负数,且当前menu是可见的,则认为当前手势是想要显示content。

*

*@return

*/

privatebooleanwantToShowContent(){

returnxUp-xDown<0&&isMenuVisible;

}

/**

*判断当前手势的意图是不是想显示menu,如果手指移动的距离是正数,且当前menu是不可见,则认为当前手势是显示menu

*

*@return

*/

privatebooleanwantToShowMenu(){

returnxUp-xDown>0&&!isMenuVisible;

}

/**

*判断是否应该滚动将menu展示出来,如果手指移动距离大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY,就认为应该滚动将menu展示出来。

*

*@return如果应该滚动将menu展示出来返回true,否则返回false。

*/

privatebooleanshouldScrollToMenu(){

returnxUp-xDown>mMenuWidth/2||getScrollVelocity()>SNAP_VELOCITY;

}

/**

*判断是否应该滚动将content展示出来,如果手指移动距离加上menuPadding大于屏幕的1/2,或者手指移动速度大于SNAP_VELOCITY,就认为应该滚动将content展示出来。

*

*@return如果应该滚动将content展示出来返回true,否则返回false。

*/

privatebooleanshouldScrollToContent(){

//这里菜单状态为显示,如果要菜单隐藏,那么手势是从右到左滑动,这里手指按下的横坐标就会比抬起时的横坐标小

returnxDown-xUp+toRightPaddingWidth>mMenuWidth/2||getScrollVelocity()>SNAP_VELOCITY;

}

/**

*获取手指在content上滑动的速度

*

*@return滑动速度,以每秒钟移动了多少像素为单位

*/

privateintgetScrollVelocity(){

mVelocityTputeCurrentVelocity(1000);

intvelocity=(int)mVelocityTracker.getXVelocity();//获取x方向的速度值

returnMath.abs(velocity);

}

/**

*回收VelocityTracker对象

*/

privatevoidrecycleVelocityTracker(){

if(null!=mVelocityTracker){

mVelocityTracker.recycle();

mVelocityTracker=null;

}

}

/**

*将屏幕滚动到menu界面,设置滚动速度为30

*/

privatevoidscrollToMenu(){

isMenuVisible=true;

newScrollTask().execute(30);

}

/**

*将屏幕滚动到content界面,设置滚动速度为-30

*/

privatevoidscrollToContent(){

isMenuVisible=false;

newScrollTask().execute(-30);

}

/**

*创建滚动任务类

*/

classScrollTaskextendsAsyncTask<Integer,Integer,Integer>{

@Override

protectedIntegerdoInBackground(Integer...speed){

intleftMargin=menuParams.leftMargin;

//根据传入的速度来滚动界面,当滚动到达左边界或右边界时跳出循环

while(true){

leftMargin=leftMargin+speed[0];

if(leftMargin>rightEdge){

leftMargin=rightEdge;

break;

}

if(leftMargin<leftEdge){

leftMargin=leftEdge;

break;

}

//更新任务进度,会把值传入到onProgressUpdate()方法中进行UI的更新

publishProgress(leftMargin);

//为了要有滚动效果产生,每次循环使线程睡眠20毫秒

sleep(20);

}

returnleftMargin;

}

/**

*这里的Intege参数对应AsyncTask中的第二个参数

*在doInBackground方法当中,,每次调用publishProgress方法都会触发onProgressUpdate执行

*onProgressUpdate是在UI线程中执行,所有可以对UI空间进行操作

*

*@paramleftMargin

*/

@Override

protectedvoidonProgressUpdate(Integer...leftMargin){

menuParams.leftMargin=leftMargin[0];

mMenu.setLayoutParams(menuParams);

}

/**

*执行异步结束,接收doInBackground()方法的返回值,接收到的返回值对应AsyncTask<Integer,Integer,Integer>第3个参数

*

*@paramleftMargin

*/

@Override

protectedvoidonPostExecute(IntegerleftMargin){

menuParams.leftMargin=leftMargin;

mMenu.setLayoutParams(menuParams);

}

}

/**

*是当前线程睡眠指定的毫秒数

*

*@parammillis

*/

privatevoidsleep(longmillis){

try{

Thread.sleep(millis);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}}以上就是整个自定义侧滑菜单控件的代码,在布局文件直接使用即可如下:<?xmlversion="1.0"encoding="utf-8"?><com.tenghu.sideslipmenu.view.SideslipMenuViewxmlns:android="/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/bg_01">

<includelayout="@layout/left_menu"/>

<LinearLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@drawable/bg_02"

android:orientation="vertical">

</LinearLayout></com.tenghu.sideslipmenu.view.SideslipMenuView>其中include引用的就是一个菜单布局文件,如下:<?xmlversion="1.0"encoding="utf-8"?><RelativeLayoutxmlns:android="/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:gravity="center_vertical">

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginLeft="30dp"

android:orientation="vertical">

<RelativeLayout

android:layout_width="wrap_content"

android:layout_height="50dp"

android:layout_marginBottom="10dp">

<ImageView

android:id="@+id/iv_img_01"

android:layout_width="50dp"

android:layout_height="match_parent"

android:src="@drawable/app_01"/>

<TextView

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginLeft="10dp"

android:layout_toRightOf="@id/iv_img_01"

android:gravity="center_vertical"

android:text="第一个Item"/>

</RelativeLayout>

<RelativeLayout

android:layout_width="wrap_content"

android:layout_height="50dp"

android:layout_marginBottom="10dp">

<ImageView

android:id="@+id/iv_img_02"

android:layout_width="50dp"

android:layout_height="match_parent"

android:src="@drawable/app_02"/>

<TextView

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginLeft="10dp"

android:layout_toRightOf="@id/iv_img_02"

android:gravity="center_vertical"

android:text="第二个Item"/>

</RelativeLayout>

<RelativeLayout

android:layout_width="wrap_content"

android:layout_height="50dp"

android:layout_marginBottom="10dp">

<ImageView

android:id="@+id/iv_img_03"

android:layout_width="50dp"

android:layout_height="match_parent"

android:src="@drawable/app_03"/>

<TextView

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_marginLeft="10dp"

android:layout_toRightOf="@id/iv_img_03"

android:gravity="center_vertical"

android:text="第三个Item"/>

</RelativeLayout>

<RelativeLayout

android:layout_width="wrap_content"

android:layout_height="50dp"

android:layout_marginBottom="10dp">

<ImageView

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论