SwipeLayout侧滑删除

package com.itheima74.swipedelete;

import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.support.v4.widget.ViewDragHelper.Callback;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

public class SwipeLayout extends FrameLayout {

	private View contentView;// item内容区域的view
	private View deleteView;// delete区域的view
	private int deleteHeight;// delete区域的高度
	private int deleteWidth;// delete区域的宽度
	private int contentWidth;// content区域的宽度
	private ViewDragHelper viewDragHelper;

	public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public SwipeLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public SwipeLayout(Context context) {
		super(context);
		init();
	}

	enum SwipeState{
		Open,Close;
	}
	
	private SwipeState currentState = SwipeState.Close;//当前默认是关闭状态
	
	private void init() {
		viewDragHelper = ViewDragHelper.create(this, callback);
	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		contentView = getChildAt(0);
		deleteView = getChildAt(1);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		deleteHeight = deleteView.getMeasuredHeight();
		deleteWidth = deleteView.getMeasuredWidth();
		contentWidth = contentView.getMeasuredWidth();
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		// super.onLayout(changed, left, top, right, bottom);
		contentView.layout(0, 0, contentWidth, deleteHeight);
		deleteView.layout(contentView.getRight(), 0, contentView.getRight()
				+ deleteWidth, deleteHeight);
	}
	
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
		
		//如果当前有打开的,则需要直接拦截,交给onTouch处理
		if(!SwipeLayoutManager.getInstance().isShouldSwipe(this)){
			//先关闭已经打开的layout
			SwipeLayoutManager.getInstance().closeCurrentLayout();
			
			result = true;
		}
		
		return result;
	}
	
	private float downX,downY;
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		//如果当前有打开的,则下面的逻辑不能执行
		if(!SwipeLayoutManager.getInstance().isShouldSwipe(this)){
			requestDisallowInterceptTouchEvent(true);
			return true;
		}
		
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			downX = event.getX();
			downY = event.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			//1.获取x和y方向移动的距离
			float moveX = event.getX();
			float moveY = event.getY();
			float delatX = moveX - downX;//x方向移动的距离
			float delatY = moveY - downY;//y方向移动的距离
			if(Math.abs(delatX)>Math.abs(delatY)){
				//表示移动是偏向于水平方向,那么应该SwipeLayout应该处理,请求listview不要拦截
				requestDisallowInterceptTouchEvent(true);
			}
			//更新downX,downY
			downX = moveX;
			downY = moveY;
			break;
		case MotionEvent.ACTION_UP:
			
			break;
		}
		viewDragHelper.processTouchEvent(event);
		return true;
	}

	private ViewDragHelper.Callback callback = new Callback() {
		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			return child==contentView||child==deleteView;
		}
		@Override
		public int getViewHorizontalDragRange(View child) {
			return deleteWidth;
		}
		@Override
		public int clampViewPositionHorizontal(View child, int left, int dx) {
			if(child==contentView){
				if(left>0)left = 0;
				if(left<-deleteWidth)left = -deleteWidth;
			}else if (child==deleteView) {
				if(left>contentWidth)left = contentWidth;
				if(left<(contentWidth-deleteWidth))left = contentWidth-deleteWidth;
			}
			return left;
		}
		@Override
		public void onViewPositionChanged(View changedView, int left, int top,
				int dx, int dy) {
			super.onViewPositionChanged(changedView, left, top, dx, dy);
			if(changedView==contentView){
				//手动移动deleteView
				deleteView.layout(deleteView.getLeft()+dx,deleteView.getTop()+dy,
						deleteView.getRight()+dx, deleteView.getBottom()+dy);
			}else if (deleteView==changedView) {
				//手动移动contentView
				contentView.layout(contentView.getLeft()+dx,contentView.getTop()+dy,
						contentView.getRight()+dx, contentView.getBottom()+dy);
			}
			
			//判断开和关闭的逻辑
			if(contentView.getLeft()==0 && currentState!=SwipeState.Close){
				//说明应该将state更改为关闭
				currentState = SwipeState.Close;
				
				//回调接口关闭的方法
				if(listener!=null){
					listener.onClose(getTag());
				}
				
				//说明当前的SwipeLayout已经关闭,需要让Manager清空一下
				SwipeLayoutManager.getInstance().clearCurrentLayout();
			}else if (contentView.getLeft()==-deleteWidth && currentState!=SwipeState.Open) {
				//说明应该将state更改为开
				currentState = SwipeState.Open;

				//回调接口打开的方法
				if(listener!=null){
					listener.onOpen(getTag());
				}
				//当前的Swipelayout已经打开,需要让Manager记录一下下
				SwipeLayoutManager.getInstance().setSwipeLayout(SwipeLayout.this);
			}
		}
		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			super.onViewReleased(releasedChild, xvel, yvel);
			if(contentView.getLeft()<-deleteWidth/2){
				//应该打开
				open();
			}else {
				//应该关闭
				close();
			}
		}
	};
	/**
	 * 打开的方法
	 */
	public void open() {
		viewDragHelper.smoothSlideViewTo(contentView,-deleteWidth,contentView.getTop());
		ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
	}
	/**
	 * 关闭的方法
	 */
	public void close() {
		viewDragHelper.smoothSlideViewTo(contentView,0,contentView.getTop());
		ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
	};
	public void computeScroll() {
		if(viewDragHelper.continueSettling(true)){
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	private OnSwipeStateChangeListener listener;
	public void setOnSwipeStateChangeListener(OnSwipeStateChangeListener listener){
		this.listener = listener;
	}
	
	public interface OnSwipeStateChangeListener{
		void onOpen(Object tag);
		void onClose(Object tag);
	}
	
}
package com.itheima74.swipedelete;

public class SwipeLayoutManager {
	private SwipeLayoutManager(){}
	private static SwipeLayoutManager mInstance = new SwipeLayoutManager();
	
	public static SwipeLayoutManager getInstance(){
		return mInstance;
	}
	
	private SwipeLayout currentLayout;//用来记录当前打开的SwipeLayout
	public void setSwipeLayout(SwipeLayout layout){
		this.currentLayout = layout;
	}
	
	/**
	 * 清空当前所记录的已经打开的layout
	 */
	public void clearCurrentLayout(){
		currentLayout = null;
	}
	
	/**
	 * 关闭当前已经打开的SwipeLayout
	 */
	public void closeCurrentLayout(){
		if(currentLayout!=null){
			currentLayout.close();
		}
	}
	
	/**
	 * 判断当前是否应该能够滑动,如果没有打开的,则可以滑动。
	 * 如果有打开的,则判断打开的layout和当前按下的layout是否是同一个
	 * 
	 * @return
	 */
	public boolean isShouldSwipe(SwipeLayout swipeLayout){
		if(currentLayout==null){
			//说明当前木有打开的layout
			return true;
		}else {
			//说明有打开的layout
			return currentLayout==swipeLayout;
		}
	}
}
发布了75 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_40387150/article/details/88573795