博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
它们的定义ListView,实现Item除去滑动和滑出菜单效果
阅读量:7237 次
发布时间:2019-06-29

本文共 14202 字,大约阅读时间需要 47 分钟。

这个程序是基于变化从网上开源项目,详情货源忘记。懒得去搜索,。假设有不合适的地方。请与我联系作者。我会及时回复和处理!

序中主要包括两个ListView,一个是实现側滑删除。一个是側滑出菜单,代码中的凝视非常全。我就不在赘述了,直接贴上核心代码和效果图,程序源代码在最后,假设有不太明确的地方能够留言评论,我会及时回复,大牛勿喷啊!

側滑删除ListView:

package com.example.testslidelistview;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.ViewConfiguration;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.ListView;import android.widget.Scroller;/** * 側滑删除Item的ListView,此处是对网上开源的一个Listview的完好。 * 实如今手指滑动时item的透明度随之改变。并添加回到原位置的动画过程 * @author zhangshuo */public class SlideListView extends ListView {	/**	 * 当前滑动的ListView position	 */	private int slidePosition;	/**	 * 手指按下X的坐标	 */	private int downY;	/**	 * 手指按下Y的坐标	 */	private int downX;	/**	 * 屏幕宽度	 */	private int screenWidth;	/**	 * ListView的item	 */	private View itemView;	/**	 * 滑动类	 */	private Scroller scroller;	private static final int SNAP_VELOCITY = 600;	/**	 * 速度追踪对象	 */	private VelocityTracker velocityTracker;	/**	 * 是否响应滑动。默觉得不响应	 */	private boolean isSlide = false;	/**	 * 觉得是用户滑动的最小距离	 */	private int mTouchSlop;	/**	 *  移除item后的回调接口	 */	private RemoveListener mRemoveListener;	/**	 *  标示是否移除	 */	private boolean isRemove = false;	/**	 * 用来指示item滑出屏幕的方向,向左或者向右,用一个枚举值来标记	 */	private RemoveDirection removeDirection;	// 滑动删除方向的枚举值	public enum RemoveDirection {		RIGHT, LEFT, NONE;	}	public SlideListView(Context context) {		this(context, null);	}	public SlideListView(Context context, AttributeSet attrs) {		this(context, attrs, 0);	}	public SlideListView(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		screenWidth = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();		scroller = new Scroller(context);		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();	}		/**	 * 设置滑动删除的回调接口	 * @param removeListener	 */	public void setRemoveListener(RemoveListener removeListener) {		this.mRemoveListener = removeListener;	}	/**	 * 分发事件,主要做的是推断点击的是那个item, 以及通过postDelayed来设置响应左右滑动事件	 */	@Override	public boolean dispatchTouchEvent(MotionEvent event) {		switch (event.getAction()) {		case MotionEvent.ACTION_DOWN: {			System.out.println("dispatch-->" + "down");			addVelocityTracker(event);			// 假如scroller滚动还没有结束。我们直接返回			if (!scroller.isFinished()) {				return false;			}			downX = (int) event.getX();			downY = (int) event.getY();			slidePosition = pointToPosition(downX, downY);			// 无效的position, 不做不论什么处理			if (slidePosition == AdapterView.INVALID_POSITION) {				return super.dispatchTouchEvent(event);			}			// 获取我们点击的item view			itemView = getChildAt(slidePosition - getFirstVisiblePosition());			break;		}		case MotionEvent.ACTION_MOVE: {			System.out.println("dispatch-->" + "move");			if (Math.abs(getScrollVelocity()) > SNAP_VELOCITY					|| (Math.abs(event.getX() - downX) > mTouchSlop && Math							.abs(event.getY() - downY) < mTouchSlop)) {				isSlide = true;							}			break;		}		case MotionEvent.ACTION_UP:			recycleVelocityTracker();			break;		}		return super.dispatchTouchEvent(event);	}	/**	 * 往右滑动。getScrollX()返回的是左边缘的距离。就是以View左边缘为原点到開始滑动的距离。所以向右边滑动为负值	 */	private void scrollRight() {		removeDirection = RemoveDirection.RIGHT;		final int delta = (screenWidth + itemView.getScrollX());		// 调用startScroll方法来设置一些滚动的參数,我们在computeScroll()方法中调用scrollTo来滚动item		scroller.startScroll(itemView.getScrollX(), 0, -delta, 0,				Math.abs(delta));		postInvalidate(); // 刷新itemView	}	/**	 * 向左滑动。依据上面我们知道向左滑动为正值	 */	private void scrollLeft() {		removeDirection = RemoveDirection.LEFT;		final int delta = (screenWidth - itemView.getScrollX());		// 调用startScroll方法来设置一些滚动的參数。我们在computeScroll()方法中调用scrollTo来滚动item		scroller.startScroll(itemView.getScrollX(), 0, delta, 0,				Math.abs(delta));		postInvalidate(); // 刷新itemView	}		/**	 *  滑动会原来的位置	 */	private void scrollBack(){		removeDirection = RemoveDirection.NONE;		scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(), 0,				Math.abs(itemView.getScrollX()));		postInvalidate(); // 刷新itemView	}	/**	 * 依据手指滚动itemView的距离来推断是滚动到開始位置还是向左或者向右滚动	 */	private void scrollByDistanceX() {		// 假设向左滚动的距离大于屏幕的二分之中的一个。就让其删除		if (itemView.getScrollX() >= screenWidth / 2) {			scrollLeft();		} else if (itemView.getScrollX() <= -screenWidth / 2) {			scrollRight();		} else {			// 滚回到原始位置			scrollBack();		}	}	/**	 * 处理我们拖动ListView item的逻辑	 */	@Override	public boolean onTouchEvent(MotionEvent ev) {		if (isSlide && slidePosition != AdapterView.INVALID_POSITION) {			System.out.println("touch-->" + "開始");			requestDisallowInterceptTouchEvent(true);			addVelocityTracker(ev);			final int action = ev.getAction();			int x = (int) ev.getX();			switch (action) {			case MotionEvent.ACTION_DOWN:				System.out.println("touch-->" + "down");				break;			case MotionEvent.ACTION_MOVE:				System.out.println("touch-->" + "move");				MotionEvent cancelEvent = MotionEvent.obtain(ev);	            cancelEvent.setAction(MotionEvent.ACTION_CANCEL |	                       (ev.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));	            onTouchEvent(cancelEvent);	            				int deltaX = downX - x;				// 手指拖动itemView滚动, deltaX大于0向左滚动,小于0向右滚				itemView.scrollTo(deltaX, 0);				// 依据手指滑动的距离,调整透明度				itemView.setAlpha(1f - Math.abs((float)deltaX/screenWidth));								return true;  //拖动的时候ListView不滚动			case MotionEvent.ACTION_UP:				System.out.println("touch-->" + "up");				// 手指离开的时候就不响应左右滚动				isSlide = false;				int velocityX = getScrollVelocity();				if (velocityX > SNAP_VELOCITY) {					scrollRight();				} else if (velocityX < -SNAP_VELOCITY) {					scrollLeft();				} else {					scrollByDistanceX();				}								recycleVelocityTracker();								break;			}		}		//否则直接交给ListView来处理onTouchEvent事件		return super.onTouchEvent(ev);	}	@Override	public void computeScroll() {		// 调用startScroll的时候scroller.computeScrollOffset()返回true,		if (scroller.computeScrollOffset()) {			// 让ListView item依据当前的滚动偏移量进行滚动			itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());						itemView.setAlpha(1f - Math.abs((float)scroller.getCurrX()/screenWidth));						postInvalidate();						// 滚动动画结束的时候调用回调接口			if (scroller.isFinished() && removeDirection != RemoveDirection.NONE) {				if (mRemoveListener == null) {					throw new NullPointerException("RemoveListener is null, we should called setRemoveListener()");				}				itemView.scrollTo(0, 0);				itemView.setAlpha(1f);				mRemoveListener.removeItem(removeDirection, slidePosition);			}		}	}	/**	 * 加入用户的速度跟踪器	 * 	 * @param event	 */	private void addVelocityTracker(MotionEvent event) {		if (velocityTracker == null) {			velocityTracker = VelocityTracker.obtain();		}		velocityTracker.addMovement(event);	}	/**	 * 移除用户速度跟踪器	 */	private void recycleVelocityTracker() {		if (velocityTracker != null) {			velocityTracker.recycle();			velocityTracker = null;		}	}	/**	 * 获取X方向的滑动速度,大于0向右滑动。反之向左	 * 	 * @return	 */	private int getScrollVelocity() {		velocityTracker.computeCurrentVelocity(1000);		int velocity = (int) velocityTracker.getXVelocity();		return velocity;	}	/**	 * 	 * 当ListView item滑出屏幕,回调这个接口	 * 我们须要在回调方法removeItem()中移除该Item,然后刷新ListView	 * 	 * @author xiaanming	 *	 */	public interface RemoveListener {		public void removeItem(RemoveDirection direction, int position);	}}
側滑菜单ListView:

package com.example.testslidelistview;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.AdapterView;import android.widget.ListView;import android.widget.Scroller;/** * 側向滑出菜单的ListView * 使用请注意与ListView的Item的布局配合。 * 该效果的实现是基于在Item的布局中通过设置PaddingLeft和PaddingRight来隐藏左右菜单的, * 所以使用此ListView时,请务必在布局Item时使用PaddingLeft和PaddingRight; * 或者自己改写此ListView,已达到想要的实现方式 * @author zhangshuo */public class SlideListView2 extends ListView {		/**禁止側滑模式*/	public static int MOD_FORBID = 0;	/**从左向右滑出菜单模式*/	public static int MOD_LEFT = 1;	/**从右向左滑出菜单模式*/	public static int MOD_RIGHT = 2;	/**左右均能够滑出菜单模式*/	public static int MOD_BOTH = 3;	/**当前的模式*/	private int mode = MOD_FORBID;	/**左側菜单的长度*/	private int leftLength = 0;	/**右側菜单的长度*/	private int rightLength = 0;		/**	 * 当前滑动的ListView position	 */	private int slidePosition;	/**	 * 手指按下X的坐标	 */	private int downY;	/**	 * 手指按下Y的坐标	 */	private int downX;	/**	 * ListView的item	 */	private View itemView;	/**	 * 滑动类	 */	private Scroller scroller;	/**	 * 觉得是用户滑动的最小距离	 */	private int mTouchSlop;	/**	 * 推断能否够側向滑动	 */	private boolean canMove = false;	/**	 * 标示是否完毕側滑	 */	private boolean isSlided = false;		public SlideListView2(Context context) {		this(context, null);	}	public SlideListView2(Context context, AttributeSet attrs) {		this(context, attrs, 0);	}	public SlideListView2(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);		scroller = new Scroller(context);		mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();	}	/**	 * 初始化菜单的滑出模式	 * @param mode	 */	public void initSlideMode(int mode){		this.mode = mode;	}		/**	 * 处理我们拖动ListView item的逻辑	 */	@Override	public boolean onTouchEvent(MotionEvent ev) {		final int action = ev.getAction();		int lastX = (int) ev.getX();		switch (action) {		case MotionEvent.ACTION_DOWN:			System.out.println("touch-->" + "down");						/*当前模式不同意滑动,则直接返回。交给ListView自身去处理*/			if(this.mode == MOD_FORBID){				return super.onTouchEvent(ev);			}						// 假设处于側滑完毕状态。側滑回去,并直接返回			if (isSlided) {				scrollBack();				return false;			}			// 假如scroller滚动还没有结束,我们直接返回			if (!scroller.isFinished()) {				return false;			}			downX = (int) ev.getX();			downY = (int) ev.getY();			slidePosition = pointToPosition(downX, downY);			// 无效的position, 不做不论什么处理			if (slidePosition == AdapterView.INVALID_POSITION) {				return super.onTouchEvent(ev);			}			// 获取我们点击的item view			itemView = getChildAt(slidePosition - getFirstVisiblePosition());						/*此处依据设置的滑动模式,自己主动获取左側或右側菜单的长度*/			if(this.mode == MOD_BOTH){				this.leftLength = -itemView.getPaddingLeft();				this.rightLength = -itemView.getPaddingRight();			}else if(this.mode == MOD_LEFT){				this.leftLength = -itemView.getPaddingLeft();			}else if(this.mode == MOD_RIGHT){				this.rightLength = -itemView.getPaddingRight();			}						break;		case MotionEvent.ACTION_MOVE:			System.out.println("touch-->" + "move");						if (!canMove					&& slidePosition != AdapterView.INVALID_POSITION					&& (Math.abs(ev.getX() - downX) > mTouchSlop && Math.abs(ev							.getY() - downY) < mTouchSlop)) {				int offsetX = downX - lastX;				if(offsetX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){					/*从右向左滑*/					canMove = true;				}else if(offsetX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){					/*从左向右滑*/					canMove = true;				}else{					canMove = false;				}				/*此段代码是为了避免我们在側向滑动时同一时候出发ListView的OnItemClickListener时间*/				MotionEvent cancelEvent = MotionEvent.obtain(ev);				cancelEvent						.setAction(MotionEvent.ACTION_CANCEL								| (ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));				onTouchEvent(cancelEvent);			}			if (canMove) {				/*设置此属性。能够在側向滑动时,保持ListView不会上下滚动*/				requestDisallowInterceptTouchEvent(true);								// 手指拖动itemView滚动, deltaX大于0向左滚动,小于0向右滚				int deltaX = downX - lastX;				if(deltaX < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){					/*向左滑*/					itemView.scrollTo(deltaX, 0);				}else if(deltaX > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){					/*向右滑*/					itemView.scrollTo(deltaX, 0);				}else{					itemView.scrollTo(0, 0);				}				return true; // 拖动的时候ListView不滚动			}		case MotionEvent.ACTION_UP:			System.out.println("touch-->" + "up");			if (canMove){				canMove = false;				scrollByDistanceX();			}			break;		}		// 否则直接交给ListView来处理onTouchEvent事件		return super.onTouchEvent(ev);	}	/**	 * 依据手指滚动itemView的距离来推断是滚动到開始位置还是向左或者向右滚动	 */	private void scrollByDistanceX() {		/*当前模式不同意滑动,则直接返回*/		if(this.mode == MOD_FORBID){			return;		}		if(itemView.getScrollX() > 0 && (this.mode == MOD_BOTH || this.mode == MOD_RIGHT)){			/*从右向左滑*/			if (itemView.getScrollX() >= rightLength / 2) {				scrollLeft();			}  else {				// 滚回到原始位置				scrollBack();			}		}else if(itemView.getScrollX() < 0 && (this.mode == MOD_BOTH || this.mode == MOD_LEFT)){			/*从左向右滑*/			if (itemView.getScrollX() <= -leftLength / 2) {				scrollRight();			} else {				// 滚回到原始位置				scrollBack();			}		}else{			// 滚回到原始位置			scrollBack();		}	}	/**	 * 往右滑动,getScrollX()返回的是左边缘的距离。就是以View左边缘为原点到開始滑动的距离,所以向右边滑动为负值	 */	private void scrollRight() {		isSlided = true;		final int delta = (leftLength + itemView.getScrollX());		// 调用startScroll方法来设置一些滚动的參数。我们在computeScroll()方法中调用scrollTo来滚动item		scroller.startScroll(itemView.getScrollX(), 0, -delta, 0,				Math.abs(delta));		postInvalidate(); // 刷新itemView	}	/**	 * 向左滑动。依据上面我们知道向左滑动为正值	 */	private void scrollLeft() {		isSlided = true;		final int delta = (rightLength - itemView.getScrollX());		// 调用startScroll方法来设置一些滚动的參数。我们在computeScroll()方法中调用scrollTo来滚动item		scroller.startScroll(itemView.getScrollX(), 0, delta, 0,				Math.abs(delta));		postInvalidate(); // 刷新itemView	}	/**	 * 滑动会原来的位置	 */	private void scrollBack() {		isSlided = false;		scroller.startScroll(itemView.getScrollX(), 0, -itemView.getScrollX(),				0, Math.abs(itemView.getScrollX()));		postInvalidate(); // 刷新itemView	}	@Override	public void computeScroll() {		// 调用startScroll的时候scroller.computeScrollOffset()返回true,		if (scroller.computeScrollOffset()) {			// 让ListView item依据当前的滚动偏移量进行滚动			itemView.scrollTo(scroller.getCurrX(), scroller.getCurrY());			postInvalidate();		}	}	/**	 * 提供给外部调用,用以将側滑出来的滑回去	 */	public void slideBack() {		this.scrollBack();	}}
注意側滑菜单ListView的使用须要配合Item布局(主要是PaddingLeft和PaddingRight这两个属性),Item布局例如以下:

截图:

好了。这里是源代码下载地址:http://download.csdn.net/detail/super_spy/7667793

版权声明:本文博客原创文章,博客,未经同意,不得转载。

你可能感兴趣的文章
Java Servlet关键点详解
查看>>
深入分析luait反编译之luajit-decomp
查看>>
从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD
查看>>
【我们一起写框架】MVVM的WPF框架(五)—完结篇
查看>>
学习ASP.NET Core Razor 编程系列十一——把新字段更新到数据库
查看>>
江山代有才人出 | 微软亚洲研究院建院二十周年
查看>>
Linux安装gitlab
查看>>
java源码-synchronized
查看>>
PostgreSQL 10.1 手册_部分 III. 服务器管理_第 21 章 数据库角色_21.2. 角色属性
查看>>
《刻意练习》读后感
查看>>
DataWorks V2.0 系列公开课
查看>>
使用 logstash, elasticsearch, kibana 搭建日志分析系统
查看>>
Android Q 将获得大量的隐私保护功能
查看>>
《恋恋笔记本》观后感
查看>>
Spring源码剖析6:Spring AOP概述
查看>>
Maven的POM.xml配置大全
查看>>
SmartRefreshLayout + BaseRecyclerviewAdapterHelper 使用MVP方式实现下拉刷新
查看>>
详解KVC(转载)
查看>>
tp5 发送阿里云短信
查看>>
cookie java spring
查看>>