Android 结合滑动控件ListView滑动删除

一转眼就15年了,希望大家15年升职加薪走上人生巅峰

这篇博客是结合上一篇ListView滑动删除之Viewgroup打造滑动控件(修正版)博客所完成的,先上个效果图吧.

技术分享

其实实现起来并不复杂

1,解决滑动冲突

因为我们的自定义滑动控件和ListView本身的滑动事件会产生各种冲突,所以我们可以自定义ListView并重写onInterceptTouchEvent方法。

我们先来了解一下android事件的分发,当用户触摸屏幕时会先去调用ViewGroup的dispatchTouchEvent方法。

而在dispathTouchEvent方法中又会调用onInterceptTouchEvent方法,这个方法主要的目的就是用来拦截用户的操作,具体的分发机制详情可以看郭神的博客 Android事件分发机制完全解析,带你从源码的角度彻底理解(下)

我们这里就先知道如果这个方法返回false则是touch事件全部由子view完成就可以,看看代码。

/**
	 * 判断是否拦截事件
	 */
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		float lastX = ev.getX();
		float lastY = ev.getY();
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mFirstX = lastX;
			mFirstY = lastY;
			int motionPosition = pointToPosition((int) mFirstX, (int) mFirstY);
			if (motionPosition >= 0) {
				currentItemView = getChildAt(motionPosition
						- getFirstVisiblePosition());
				mySwipeItem = (MySwipeItem) currentItemView
						.findViewById(R.id.myitem);
			}
			break;
		case MotionEvent.ACTION_MOVE:
			float dx = lastX - mFirstX;
			float dy = lastY - mFirstY;
			Log.d("TAG", "DX:" + dx);
			if (Math.abs(dx) >= 5 && Math.abs(dy) >= 5) {
				return false;
			}
			if (Math.abs(dx) < 5 && Math.abs(dx) > 0) {
				mySwipeItem.toOff();
			}
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}

在这里我就是在move的时候做判断,如果条件满足我们就认为用户是在进行横向滑动操作,而在down的时候获取到listview的子view,当move条件不满足开始进行纵向滑动的时候使控件关闭。

2,使用回调接口

我们的效果为如果滑开了这个控件下次再点击除button以外的地方就关闭滑动控件,我们可以使用接口回调来实现这个效果

	public interface OnScrollState {
		public void scrollView();
		public void scrollOn(View view);
	}

	public void setOnScrollState(OnScrollState onScrollState) {
		this.mOnScrollState = onScrollState;
	}
自定义了一个接口然后在touch的时候进行判断

@Override
	public boolean onTouchEvent(MotionEvent event) {
		int scrollX = getScrollX();
		int x = (int) event.getX();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN: {
			if (!mScroller.isFinished()) {
				mScroller.abortAnimation();
			}
			if (mOnScrollState != null) {
				mOnScrollState.scrollView();
			}
			break;
		}
		case MotionEvent.ACTION_MOVE: {
			int deltaX = x - lastX;
			// 计算滑动终点是否合法,防止滑动越界
			int newScrollX = scrollX - deltaX;
			if (deltaX != 0) {
				if (newScrollX < 0) {
					newScrollX = 0;
				} else if (newScrollX > mMaxDistancex) {
					newScrollX = mMaxDistancex;
				}
				this.scrollTo(newScrollX, 0);
			}
			break;
		}
		case MotionEvent.ACTION_UP: {
			int newScrollX = 0;
			// 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置
			if (scrollX > mMaxDistancex / 2) {
				newScrollX = mMaxDistancex;
			}
			// 慢慢滑向终点
			this.smoothScrollTo(newScrollX, 0);
			if (mOnScrollState != null && newScrollX == mMaxDistancex) {
				mOnScrollState.scrollOn(this);
			}
			break;
		}
		}
		lastX = x;
		return true;
	}
在Main中进行调用控件的关闭方法

	@Override
	public void scrollView() {
		if (mLastItem != null) {
			mLastItem.toOff();
		}
	}

	@Override
	public void scrollOn(View view) {
		mLastItem = (MySwipeItem) view;
	}

3,缺点

很简单就实现了滑动效果不是么。。。。但是我们会发现我们自己的listview的onItemClick方法不起作用了!!,因为我们重写了onInterceptTouchEvent方法,但是我们的滑动控件中的textView以及button还是可以用onclick的,所以还有一种listview的滑动删除方法高仿微信对话列表滑动删除效果

4,后记

不要问我为什么自己不写一个完美的,我才不会说是因为我写不出来又犯懒了。。。。新手可以学习借鉴了解一下android的分发机制,但要是真的要用到项目中,我还是建议去Github上down一个成熟的


项目源码





郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。