当前位置: 首页 > 科技观察

Android自定义View-SlideListView

时间:2023-03-13 21:18:01 科技观察

在android中,ListView可以说是使用最多的控件之一。ListView有很多用法和处理事件,比如item点击和长按事件。在更多的应用中,点击是跳转,长按会弹出一些选择菜单等。这里要介绍的是一个ListView侧滑菜单的自定义控件渲染如下:常态侧滑菜单状态分析主要用到Scroller滑动类,首先拦截触摸事件是当action==MotionEvent.ACTION_DOWN时,根据退出点获取我们点击的itemView,然后根据滑动方式自动获取左侧或右侧的宽度(向左或向右滑动);在action==MotionEvent.ACTION_MOVE中,根据移动判断是否可以侧滑,侧滑方向,使用itemView.scrollTo(deltaX,0);移动itemView;***动作中判断模式和移动距离==MotionEvent.ACTION_UP完成侧滑或回到初始状态。实现第一步初始化Scrollerscroller=newScroller(context);mTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();第二步动作==MotionEvent.ACTION_DOWNcaseMotionEvent.ACTION_DOWN:if(this.mode==MOD_FORBID){returnsuper.onTouchEvent(ev);}//如果侧滑完成,向后滑动,直接返回if(isSlided){scrollBack();返回假;}//如果scroller滚动还没有结束,我们直接返回if(!scroller.isFinished()){returnfalse;}downX=(int)ev.getX();downY=(int)ev.getY();slidePosition=pointToPosition(downX,downY);//无效位置,不做任何处理if(slidePosition==AdapterView.INVALID_POSITION){returnsuper.onTouchEvent(ev);}//获取我们点击的itemviewitemView=getChildAt(slidePosition-getFirstVisiblePosition());/*这里根据设置的滑动模式自动获取左右菜单的长度*/if(this.mode==MOD_BOTH){this.leftLength=-itemView.getPaddingLeft();this.rightLength=-itemView.getPaddingRight();}elseif(this.mode==MOD_LEFT){this.leftLength=-itemView.getPaddingLeft();}elseif(this.mode==MOD_RIGHT){this.rightLength=-itemView.getPaddingRight();}break;第三步动作==MotionEvent.ACTION_MOVEcaseMotionEvent.ACTION_MOVE:if(!canMove&&slidePosition!=AdapterView.INVALID_POSITION&&(Math.abs(ev.getX()-downX)>mTouchSlop&&Math.abs(ev.getY()-downY)0&&(this.mode==MOD_BOTH||this.mode==MOD_RIGHT)){/*从右向左滑动*/canMove=true;}elseif(offsetX<0&&(this.mode==MOD_BOTH||this.mode==MOD_LEFT)){/*从左向右滑动*/canMove=true;}else{canMove=false;}/*这段代码是为了避免侧滑时触发ListView的OnItemClickListener时间*/MotionEventcancelEvent=MotionEvent.obtain(ev);cancelEvent.setAction(MotionEvent.ACTION_CANCEL|(ev.getActionIndex()<0&&(this.mode==MOD_BOTH||this.mode==MOD_RIGHT)){/*向右滑动*/itemView.scrollTo(deltaX,0);}else{itemView.scrollTo(0,0);返回真;}休息;第四步action==MotionEvent.ACTION_UPcaseMotionEvent.ACTION_UP:if(mSwipeLayout!=null)mSwipeLayout.setEnabled(true);//requestDisallowInterceptTouchEvent(false);如果(可以移动){可以移动=假;scrollByDistanceX();}休息;完整代码以下是完整代码包com.jwenfeng。快速开发视图;importandroid.content.Context;importandroid.support.v4.widget.SwipeRefreshLayout;importandroid.util.AttributeSet;importandroid.view.MotionEvent;importandroid.view.View;importandroid.view.ViewConfiguration;importandroid.widget.ListView;importandroid.widget.Scroller;/***当前类注释:ListView滑出菜单*项目名称:fastdev*包名称:com.jwenfeng.fastdev.view*作者:jinwenfengon16/4/1110:55*Email:823546371@qq.com*QQ:823546371*公司:南京沐尊信息科技Co.,Ltd.*?2016jinwenfeng*?版权所有,未经许可不得传播*/publicclassSlideListViewextendsListView{/**下拉刷新视图*/privateSwipeRefreshLayoutmSwipeLayout;/***禁止侧滑模式*/publicstaticintMOD_FORBID=0;/***从左到右右滑出菜单模式*/publicstaticintMOD_LEFT=1;/***从右向左滑出菜单模式*/publicstaticintMOD_RIGHT=2;/***两侧滑出菜单模式*/publicstaticintMOD_BOTH=3;/***当前模式*/privateintmode=MOD_FORBID;/***左侧菜单的长度*/privateintleftLength=0;/***右侧菜单的长度*/privateintrightLength=0;/***当前滑动的ListView 位置*/privateintslidePosition;/***手指按下X的坐标*/privateintdownY;/***手指按下Y的坐标*/privateintdownX;/***ListView的项目*/privateViewitemView;/***滑动类*/privateScrollerscroller;/***被认为是用户滑动的最小距离*/privateintmTouchSlop;/***判断是否可以侧滑*/privatebooleancanMove=false;/***表示侧滑是否完成*/privatebooleanisSlided=false;publicSlideListView(Contextcontext){这个(上下文,null);}publicSlideListView(Contextcontext,AttributeSetattrs){this(context,attrs,0);}publicSlideListView(Contextcontext,AttributeSetattrs,intdefStyleAttr){super(context,attrs,defStyleAttr);滚动条=newScroller(上下文);mTouchSlop=ViewConfiguration.get(getContext()).getScaledTouchSlop();}/***初始化菜单滑出模式**@parammode*/publicvoidinitSlideMode(intmode){this.mode=mode;}/***处理我们拖动ListViewitem的逻辑*/@OverridepublicbooleanonTouchEvent(MotionEventev){finalintaction=ev.getAction();intlastX=(int)ev.getX();switch(action){caseMotionEvent.ACTION_DOWN:if(this.mode==MOD_FORBID){returnsuper.onTouchEvent(ev);}//如果侧滑完成,向后滑动,直接返回if(isSlided){scrollBack();返回假;}//如果scroller还没有滚动结束,我们直接返回if(!scroller.isFinished()){returnfalse;}downX=(int)ev.getX();downY=(int)ev.getY();slidePosition=pointToPosition(downX,downY);//无效位置,什么都不做if(slidePosition==AdapterView.INVALID_POSITION){returnsuper.onTouchEvent(ev);}//获取我们点击的itemviewitemView=getChildAt(slidePosition-getFirstVisiblePosition());/*这里根据设置的滑动方式自动获取左右菜单的长度*/if(this.mode==MOD_BOTH){this.leftLength=-itemView.getPaddingLeft();this.rightLength=-itemView.getPaddingRight();}elseif(this.mode==MOD_LEFT){this.leftLength=-itemView。getPaddingLeft();}elseif(this.mode==MOD_RIGHT){this.rightLength=-itemView.getPaddingRight();}休息;caseMotionEvent.ACTION_MOVE:if(!canMove&&slidePosition!=AdapterView.INVALID_POSITION&&(Math.abs(ev.getX()-downX)>mTouchSlop&&Math.abs(ev.getY()-downY)0&&(this.mode==MOD_BOTH||this.mode==MOD_RIGHT)){/*从右向左滑动*/canMove=true;}elseif(offsetX<0&&(this.mode==MOD_BOTH||this.mode==MOD_LEFT)){/*从左向右滑动*/canMove=true;}else{canMove=false;}/*这段代码是为了避免侧滑时触发ListView的OnItemClickListener时间*/MotionEventcancelEvent=MotionEvent.obtain(ev);cancelEvent.setAction(MotionEvent.ACTION_CANCEL|(ev.getActionIndex()<0&&(this.mode==MOD_BOTH||this.mode==MOD_RIGHT)){/*向右滑动*/itemView.scrollTo(deltaX,0);}else{itemView.scrollTo(0,0);返回真;}休息;caseMotionEvent.ACTION_UP:if(mSwipeLayout!=null)mSwipeLayout.setEnabled(true);//requestDisallowInterceptTouchEvent(false);如果(可以移动){可以移动=假;scrollByDistanceX();}休息;}returnsuper.onTouchEvent(ev);}privatevoidscrollByDistanceX(){if(this.mode==MOD_FORBID){返回;}if(itemView.getScrollX()>0&&(this.mode==MOD_BOTH||this.mode==MOD_RIGHT)){/*从右向左滑动*/if(itemView.getScrollX()>=rightLength/2){向左滚动();}else{//滚动回到原来的位置scrollBack();}}elseif(itemView.getScrollX()<0&&(this.mode==MOD_BOTH||this.mode==MOD_LEFT)){/*从左向右滑动*/if(itemView.getScrollX()<=-leftLength/2){滚动右();}else{//滚动回到原来的位置scrollBack();}}else{//滚动回到原来的位置scrollBack();}}/***向右滑动,getScrollX()返回的是距离左边缘的距离,也就是View的左边缘到滑动开始的距离,所以向右滑动是负值*/privatevoidscrollRight(){isSlided=true;finalintdelta=(leftLength+itemView.getScrollX());//调用startScroll方法设置一些滚动参数,我们在computeScroll()方法中调用scrollTo来滚动itemscroller.startScroll(itemView.getScrollX(),0,-delta,0,Math.abs(delta));postInvalidate();//刷新itemView}/***向左滑动,根据上面我们知道向左滑动是正值*/privatevoidscrollLeft(){isSlided=true;finalintdelta=(rightLength-itemView.getScrollX());//调用startScroll方法设置一些滚动参数,我们在computeScroll()方法中调用scrollTo来滚动itemscroller.startScroll(itemView.getScrollX(),0,delta,0,Math.abs(delta));postInvalidate();//刷新itemView}privatevoidscrollBack(){isSlided=false;scroller.startScroll(itemView.getScrollX(),0,-itemView.getScrollX(),0,Math.abs(itemView.getScrollX()));postInvalidate();//刷新itemView}@OverridepublicvoidcomputeScroll(){//调用startScroll时Scroller.computeScrollOffset()返回true,if(scroller.computeScrollOffset()){//让ListViewitem根据当前滚动偏移量滚动itemView.scrollTo(scroller.getCurrX(),scroller.getCurrY());后无效();}}/***提供给外部调用,向后滑出侧滑*/publicvoidslideBack(){this.scrollBack();}publicvoidsetSwipeLayout(SwipeRefreshLayoutmSwipeLayout){this.mSwipeLayout=mSwipeLayout;}}