版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】自定义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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 互联网在线审批系统技术设计方案
- 2021年中国痛风与高尿酸血症临床诊治指南
- 2024年红细胞类诊断抗原项目建议书
- 物流营销与客户关系 课件全套 张广敬 项目1-9 初识物流营销和客户关系-评估物流营销绩效
- 电子线路装调 课件 A1-5能正确识别晶闸管
- 2024年各类型谱仪(含多道系统)项目建议书
- 2024年金融私募项目发展计划
- “双减”背景下区域教研如何赋能学科教师
- 2024年PP-R再生料项目合作计划书
- 2024年加气混凝土砌块项目合作计划书
- 文化旅游安全培训
- 2024届广东省广州市普通高中毕业班下学期一模考试语文试题讲评课件
- 2024年福建泉州丰泽水务有限公司招聘笔试参考题库附带答案详解
- 肺栓塞疑难病例讨论
- 教科版小学科学新版二年级下册科学《测试反应快慢》教学课件
- 企业培训课件剪映模板
- 果树栽培技术教案(全)
- 老年人静脉血栓栓塞症防治中国专家共识2023
- 数据中心微电网设计与综合优化
- 广东工贸职业技术学院模板-精美原创毕业论文答辩
- 小班科学课件《夏天的声音》
评论
0/150
提交评论