已经整好了listView,后续需要加入右滑删除,在网上查了一堆资料,最终整理了一个无侵入性的
1.建立SwipeItemLayout (作为子项item的最外层布局)
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class SwipeItemLayout extends ViewGroup {
enum Mode{
RESET,DRAG,FLING,TAP
}
private Mode mTouchMode;
private ViewGroup mMainView;
private ViewGroup mSideView;
private ScrollRunnable mScrollRunnable;
private int mScrollOffset;
private int mMaxScrollOffset;
private boolean mInLayout;
private boolean mIsLaidOut;
public SwipeItemLayout(Context context) {
this(context,null);
}
public SwipeItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchMode = Mode.RESET;
mScrollOffset = 0;
mScrollRunnable = new ScrollRunnable(context);
}
public boolean isOpen(){
return mScrollOffset !=0;
}
Mode getTouchMode(){
return mTouchMode;
}
void setTouchMode(Mode mode){
switch (mTouchMode){
case FLING:
mScrollRunnable.abort();
break;
case RESET:
break;
}
mTouchMode = mode;
}
public void open(){
if(mScrollOffset!=-mMaxScrollOffset){
//正在open,不需要处理
if(mTouchMode== Mode.FLING && mScrollRunnable.isScrollToLeft())
return;
//当前正在向右滑,abort
if(mTouchMode== Mode.FLING /*&& !mScrollRunnable.mScrollToLeft*/)
mScrollRunnable.abort();
mScrollRunnable.startScroll(mScrollOffset,-mMaxScrollOffset);
}
}
public void close(){
if(mScrollOffset!=0){
//正在close,不需要处理
if(mTouchMode== Mode.FLING && !mScrollRunnable.isScrollToLeft())
return;
//当前正向左滑,abort
if(mTouchMode== Mode.FLING /*&& mScrollRunnable.mScrollToLeft*/)
mScrollRunnable.abort();
mScrollRunnable.startScroll(mScrollOffset,0);
}
}
void fling(int xVel){
mScrollRunnable.startFling(mScrollOffset,xVel);
}
void revise(){
if(mScrollOffset<-mMaxScrollOffset/2)
open();
else
close();
}
boolean trackMotionScroll(int deltaX){
if(deltaX==0)
return false;
boolean over = false;
int newLeft = mScrollOffset+deltaX;
if((deltaX>0 && newLeft>0) || (deltaX<0 && newLeft<-mMaxScrollOffset)){
over = true;
newLeft = Math.min(newLeft,0);
newLeft = Math.max(newLeft,-mMaxScrollOffset);
}
offsetChildrenLeftAndRight(newLeft-mScrollOffset);
mScrollOffset = newLeft;
return over;
}
private boolean ensureChildren(){
int childCount = getChildCount();
if(childCount!=2)
return false;
View childView = getChildAt(0);
if(!(childView instanceof ViewGroup))
return false;
mMainView = (ViewGroup) childView;
childView = getChildAt(1);
if(!(childView instanceof ViewGroup))
return false;
mSideView = (ViewGroup) childView;
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!ensureChildren())
throw new RuntimeException("SwipeItemLayout的子视图不符合规定");
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
MarginLayoutParams lp = null;
int horizontalMargin,verticalMargin;
int horizontalPadding = getPaddingLeft()+getPaddingRight();
int verticalPadding = getPaddingTop()+getPaddingBottom();
lp = (MarginLayoutParams) mMainView.getLayoutParams();
horizontalMargin = lp.leftMargin+lp.rightMargin;
verticalMargin = lp.topMargin+lp.bottomMargin;
measureChildWithMargins(mMainView,
widthMeasureSpec,horizontalMargin+horizontalPadding,
heightMeasureSpec,verticalMargin+verticalPadding);
if(widthMode== MeasureSpec.AT_MOST)
widthSize = Math.min(widthSize,mMainView.getMeasuredWidth()+horizontalMargin+horizontalPadding);
else if(widthMode== MeasureSpec.UNSPECIFIED)
widthSize = mMainView.getMeasuredWidth()+horizontalMargin+horizontalPadding;
if(heightMode== MeasureSpec.AT_MOST)
heightSize = Math.min(heightSize,mMainView.getMeasuredHeight()+verticalMargin+verticalPadding);
else if(heightMode== MeasureSpec.UNSPECIFIED)
heightSize = mMainView.getMeasuredHeight()+verticalMargin+verticalPadding;
setMeasuredDimension(widthSize,heightSize);
//side layout大小为自身实际大小
lp = (MarginLayoutParams) mSideView.getLayoutParams();
verticalMargin = lp.topMargin+lp.bottomMargin;
mSideView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(getMeasuredHeight()-verticalMargin-verticalPadding, MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(!ensureChildren())
throw new RuntimeException("SwipeItemLayout的子视图不符合规定");
mInLayout = true;
int pl = getPaddingLeft();
int pt = getPaddingTop();
int pr = getPaddingRight();
int pb = getPaddingBottom();
MarginLayoutParams mainLp = (MarginLayoutParams) mMainView.getLayoutParams();
MarginLayoutParams sideParams = (MarginLayoutParams) mSideView.getLayoutParams();
int childLeft = pl+mainLp.leftMargin;
int childTop = pt+mainLp.topMargin;
int childRight = getWidth()-(pr+mainLp.rightMargin);
int childBottom = getHeight()-(mainLp.bottomMargin+pb);
mMainView.layout(childLeft,childTop,childRight,childBottom);
childLeft = childRight+sideParams.leftMargin;
childTop = pt+sideParams.topMargin;
childRight = childLeft+sideParams.leftMargin+sideParams.rightMargin+mSideView.getMeasuredWidth();
childBottom = getHeight()-(sideParams.bottomMargin+pb);
mSideView.layout(childLeft,childTop,childRight,childBottom);
mMaxScrollOffset = mSideView.getWidth()+sideParams.leftMargin+sideParams.rightMargin;
mScrollOffset = 0;//mScrollOffset<-mMaxScrollOffset/2 ? -mMaxScrollOffset:0;
//offsetChildrenLeftAndRight(mScrollOffset);
mInLayout = false;
mIsLaidOut = true;
}
void offsetChildrenLeftAndRight(int delta){
ViewCompat.offsetLeftAndRight(mMainView,delta);
ViewCompat.offsetLeftAndRight(mSideView,delta);
}
@Override
public void requestLayout() {
if (!mInLayout) {
super.requestLayout();
}
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
protected LayoutParams generateLayoutParams(LayoutParams p) {
return p instanceof MarginLayoutParams ? p : new MarginLayoutParams(p);
}
@Override
protected boolean checkLayoutParams(LayoutParams p) {
return p instanceof MarginLayoutParams && super.checkLayoutParams(p);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if(mScrollOffset!=0 && mIsLaidOut){
offsetChildrenLeftAndRight(-mScrollOffset);
mScrollOffset = 0;
}else
mScrollOffset = 0;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if(mScrollOffset!=0 && mIsLaidOut){
offsetChildrenLeftAndRight(-mScrollOffset);
mScrollOffset = 0;
}else
mScrollOffset = 0;
removeCallbacks(mScrollRunnable);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
//click main view,但是它处于open状态,所以,不需要点击效果,直接拦截不调用click listener
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
View pointView = findTopChildUnder(this,x,y);
if(pointView!=null && pointView==mMainView && mScrollOffset !=0)
return true;
break;
}
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:{
final int x = (int) ev.getX();
final int y = (int) ev.getY();
View pointView = findTopChildUnder(this,x,y);
if(pointView!=null && pointView==mMainView && mTouchMode== Mode.TAP && mScrollOffset !=0)
return true;
break;
}
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
//click main view,但是它处于open状态,所以,不需要点击效果,直接拦截不调用click listener
switch (action) {
case MotionEvent.ACTION_DOWN: {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
View pointView = findTopChildUnder(this,x,y);
if(pointView!=null && pointView==mMainView && mScrollOffset !=0)
return true;
break;
}
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:{
final int x = (int) ev.getX();
final int y = (int) ev.getY();
View pointView = findTopChildUnder(this,x,y);
if(pointView!=null && pointView==mMainView && mTouchMode== Mode.TAP && mScrollOffset !=0) {
close();
return true;
}
break;
}
}
return false;
}
@Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if(getVisibility()!= View.VISIBLE){
mScrollOffset = 0;
invalidate();
}
}
private static final Interpolator sInterpolator = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
class ScrollRunnable implements Runnable {
private static final int FLING_DURATION = 200;
private Scroller mScroller;
private boolean mAbort;
private int mMinVelocity;
private boolean mScrollToLeft;
ScrollRunnable(Context context){
mScroller = new Scroller(context,sInterpolator);
mAbort = false;
mScrollToLeft = false;
ViewConfiguration configuration = ViewConfiguration.get(context);
mMinVelocity = configuration.getScaledMinimumFlingVelocity();
}
void startScroll(int startX,int endX){
if(startX!=endX){
Log.e("scroll - startX - endX",""+startX+" "+endX);
setTouchMode(Mode.FLING);
mAbort = false;
mScrollToLeft = endX<startX;
mScroller.startScroll(startX,0,endX-startX,0, 400);
ViewCompat.postOnAnimation(SwipeItemLayout.this,this);
}
}
void startFling(int startX,int xVel){
Log.e("fling - startX",""+startX);
if(xVel>mMinVelocity && startX!=0) {
startScroll(startX, 0);
return;
}
if(xVel<-mMinVelocity && startX!=-mMaxScrollOffset) {
startScroll(startX, -mMaxScrollOffset);
return;
}
startScroll(startX,startX>-mMaxScrollOffset/2 ? 0:-mMaxScrollOffset);
}
void abort(){
if(!mAbort){
mAbort = true;
if(!mScroller.isFinished()){
mScroller.abortAnimation();
removeCallbacks(this);
}
}
}
//是否正在滑动需要另外判断
boolean isScrollToLeft(){
return mScrollToLeft;
}
@Override
public void run() {
Log.e("abort", Boolean.toString(mAbort));
if(!mAbort){
boolean more = mScroller.computeScrollOffset();
int curX = mScroller.getCurrX();
Log.e("curX",""+curX);
boolean atEdge = trackMotionScroll(curX-mScrollOffset);
if(more && !atEdge) {
ViewCompat.postOnAnimation(SwipeItemLayout.this, this);
return;
}
if(atEdge){
removeCallbacks(this);
if(!mScroller.isFinished())
mScroller.abortAnimation();
setTouchMode(Mode.RESET);
}
if(!more){
setTouchMode(Mode.RESET);
//绝对不会出现这种意外的!!!可以注释掉
if(mScrollOffset!=0){
if(Math.abs(mScrollOffset)>mMaxScrollOffset/2)
mScrollOffset = -mMaxScrollOffset;
else
mScrollOffset = 0;
ViewCompat.postOnAnimation(SwipeItemLayout.this,this);
}
}
}
}
}
static View findTopChildUnder(ViewGroup parent, int x, int y) {
final int childCount = parent.getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
final View child = parent.getChildAt(i);
if (x >= child.getLeft() && x < child.getRight()
&& y >= child.getTop() && y < child.getBottom()) {
return child;
}
}
return null;
}
}
2.建立SwipeListView (替换listView)
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.ViewGroup;
import android.view.ViewParent;
import android.widget.ListView;
import com.huoduoduo.shipmerchant.module.main.others.SwipeItemLayout.Mode;
public class SwipeListView extends ListView {
private SwipeItemLayout mCaptureItem;
private float mLastMotionX;
private float mLastMotionY;
private VelocityTracker mVelocityTracker;
private int mActivePointerId;
private int mTouchSlop;
private int mMaximumVelocity;
private boolean mDragHandleBySuper;
private boolean mDragHandleByThis;
//如果item open,此时点击其它地方就close item,并且完全不处理后续的所以消息(即此时滑动不起作用了)。
private boolean mIsCancelEvent;
public SwipeListView(Context context) {
this(context,null);
}
public SwipeListView(Context context, AttributeSet attrs) {
super(context, attrs);
ViewConfiguration configuration = ViewConfiguration.get(context);
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
mActivePointerId = -1;
mDragHandleBySuper = false;
mDragHandleByThis = false;
mIsCancelEvent = false;
}
@Override
public boolean canScrollVertically(int direction) {
return mDragHandleByThis
|| (mCaptureItem!=null && mCaptureItem.isOpen())
|| mIsCancelEvent
||super.canScrollVertically(direction);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
if(mIsCancelEvent && action!= MotionEvent.ACTION_UP && action!= MotionEvent.ACTION_CANCEL)
return true;
else if(mIsCancelEvent){
cancel();
return true;
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (action){
case MotionEvent.ACTION_DOWN:{
mIsCancelEvent = false;
mActivePointerId = ev.getPointerId(0);
final float x = ev.getX(0);
final float y = ev.getY(0);
mLastMotionX = x;
mLastMotionY = y;
boolean pointOther = false;
SwipeItemLayout pointItem = null;
//首先知道ev针对的是哪个item
View pointView = SwipeItemLayout.findTopChildUnder(this,(int)x,(int)y);
if(pointView==null || !(pointView instanceof SwipeItemLayout))
pointOther = true;//可能是head view、bottom view或者其它类型的item
else
pointItem = (SwipeItemLayout) pointView;
//此时的pointOther=true,意味着点击的view为空或者点击的不是item
//还没有把点击的是item但是不是capture item给过滤出来
if(!pointOther && (mCaptureItem==null || mCaptureItem!=pointItem))
pointOther = true;
//点击的是capture item
if(!pointOther){
Mode touchMode = mCaptureItem.getTouchMode();
//如果它在fling,就转为drag
//需要拦截,并且requestDisallowInterceptTouchEvent
boolean disallowIntercept = false;
if(touchMode== Mode.FLING){
mCaptureItem.setTouchMode(Mode.DRAG);
disallowIntercept = true;
mDragHandleByThis = true;
}else {//如果是expand的,就不允许parent拦截
mCaptureItem.setTouchMode(Mode.TAP);
if(mCaptureItem.isOpen())
disallowIntercept = true;
}
if(disallowIntercept){
final ViewParent parent = getParent();
if (parent!= null)
parent.requestDisallowInterceptTouchEvent(true);
}
}else{//capture item为null或者与point item不一样
//直接将其close掉
if(mCaptureItem!=null && mCaptureItem.isOpen()) {
mCaptureItem.close();
mIsCancelEvent = true;
return true;
}
if(pointItem!=null) {
mCaptureItem = pointItem;
mCaptureItem.setTouchMode(Mode.TAP);
}
}
//如果parent处于fling状态,此时,parent就会转为drag。此时,应该将后续move都交给parent处理
if(!mDragHandleByThis)
mDragHandleBySuper = super.onInterceptTouchEvent(ev);
return mDragHandleByThis || mDragHandleBySuper;
}
case MotionEvent.ACTION_POINTER_UP: {
final int actionIndex = ev.getActionIndex();
final int pointerId = ev.getPointerId(actionIndex);
if (pointerId == mActivePointerId) {
final int newIndex = actionIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newIndex);
mLastMotionX = ev.getX(newIndex);
mLastMotionY = ev.getY(newIndex);
}
return super.onInterceptTouchEvent(ev);
}
//down时,已经将capture item定下来了。所以,后面可以安心考虑event处理
case MotionEvent.ACTION_MOVE: {
//在down时,就被认定为parent的drag,所以,直接交给parent处理即可
if(mDragHandleBySuper) {
if(mCaptureItem!=null)
mCaptureItem.close();
return super.onInterceptTouchEvent(ev);
}
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
if (activePointerIndex == -1)
break;
final int x = (int) (ev.getX(activePointerIndex)+.5f);
final int y = (int) ((int) ev.getY(activePointerIndex)+.5f);
int deltaX = (int) (x - mLastMotionX);
int deltaY = (int)(y-mLastMotionY);
final int xDiff = Math.abs(deltaX);
final int yDiff = Math.abs(deltaY);
if(mCaptureItem!=null){
Mode touchMode = mCaptureItem.getTouchMode();
if(touchMode== Mode.TAP ){
//如果capture item是open的,下拉有两种处理方式:
// 1、下拉后,直接close item
// 2、只要是open的,就拦截所有它的消息,这样如果点击open的,就只能滑动该capture item
//网易邮箱,在open的情况下,下拉直接close
//QQ,在open的情况下,下拉也是close。但是,做的不够好,没有达到该效果。
if(xDiff>mTouchSlop && xDiff>yDiff){
mDragHandleByThis = true;
mCaptureItem.setTouchMode(Mode.DRAG);
final ViewParent parent = getParent();
parent.requestDisallowInterceptTouchEvent(true);
deltaX = deltaX>0 ? deltaX-mTouchSlop:deltaX+mTouchSlop;
}else{
//表明不是水平滑动,即不判定为SwipeItemLayout的滑动
//但是,可能是下拉刷新SwipeRefreshLayout或者RecyclerView的滑动
//一般的下拉判定,都是yDiff>mTouchSlop,所以,此处这么写不会出问题
//这里这么做以后,如果判定为下拉,就直接close
mDragHandleBySuper = super.onInterceptTouchEvent(ev);
}
}
touchMode = mCaptureItem.getTouchMode();
if(touchMode== Mode.DRAG){
mLastMotionX = x;
mLastMotionY = y;
//对capture item进行拖拽
mCaptureItem.trackMotionScroll(deltaX);
}
}else
mDragHandleBySuper = super.onInterceptTouchEvent(ev);
if(mDragHandleBySuper && mCaptureItem!=null)
mCaptureItem.close();
return mDragHandleByThis || mDragHandleBySuper;
}
case MotionEvent.ACTION_UP:
boolean ret = false;
if(mDragHandleByThis && mCaptureItem!=null/**起始一定不为null*/){
Mode touchMode = mCaptureItem.getTouchMode();
if(touchMode== Mode.DRAG){
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int xVel = (int) velocityTracker.getXVelocity(mActivePointerId);
mCaptureItem.fling(xVel);
ret = true;
}
}else
ret = super.onInterceptTouchEvent(ev);
cancel();
return ret;
case MotionEvent.ACTION_CANCEL:
if(mCaptureItem!=null)
mCaptureItem.revise();
super.onInterceptTouchEvent(ev);
cancel();
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getActionMasked();
final int actionIndex = ev.getActionIndex();
if(mIsCancelEvent && action!= MotionEvent.ACTION_UP && action!= MotionEvent.ACTION_CANCEL)
return true;
else if(mIsCancelEvent){
cancel();
return true;
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
switch (action){
case MotionEvent.ACTION_DOWN:
//如果调用super.onTouchEvent(ev);必然导致super.onInterceptTouchEvent(ev)无法返回true,所以不能调用它,直接返回true
//但是super.onTouchEvent(ev)就无法处理DOWN消息,从而无法处理item click。所以,只能通过click listener的方式来处理点击消息!!!
//不调用的问题在于会导致没有item click效果、没有flywheel效果
return super.onTouchEvent(ev);
case MotionEvent.ACTION_POINTER_DOWN:
mActivePointerId = ev.getPointerId(actionIndex);
mLastMotionX = ev.getX(actionIndex);
mLastMotionY = ev.getY(actionIndex);
return super.onTouchEvent(ev);
case MotionEvent.ACTION_POINTER_UP:
final int pointerId = ev.getPointerId(actionIndex);
if(pointerId==mActivePointerId){
final int newIndex = actionIndex == 0 ? 1 : 0;
mActivePointerId = ev.getPointerId(newIndex);
mLastMotionX = ev.getX(newIndex);
mLastMotionY = ev.getY(newIndex);
}
return super.onTouchEvent(ev);
case MotionEvent.ACTION_MOVE: {
//在down时,就被认定为parent的drag,所以,直接交给parent处理即可
if(mDragHandleBySuper) {
if(mCaptureItem!=null)
mCaptureItem.close();
return super.onTouchEvent(ev);
}
final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
if (activePointerIndex == -1)
break;
final int x = (int) (ev.getX(activePointerIndex)+.5f);
final int y = (int) ((int) ev.getY(activePointerIndex)+.5f);
int deltaX = (int) (x - mLastMotionX);
int deltaY = (int)(y-mLastMotionY);
final int xDiff = Math.abs(deltaX);
final int yDiff = Math.abs(deltaY);
if(mCaptureItem!=null){
Mode touchMode = mCaptureItem.getTouchMode();
if(touchMode== Mode.TAP ){
//如果capture item是open的,下拉有两种处理方式:
// 1、下拉后,直接close item
// 2、只要是open的,就拦截所有它的消息,这样如果点击open的,就只能滑动该capture item
//网易邮箱,在open的情况下,下拉直接close
//QQ,在open的情况下,下拉也是close。但是,做的不够好,没有达到该效果。
if(xDiff>mTouchSlop && xDiff>yDiff){
mDragHandleByThis = true;
mCaptureItem.setTouchMode(Mode.DRAG);
final ViewParent parent = getParent();
parent.requestDisallowInterceptTouchEvent(true);
deltaX = deltaX>0 ? deltaX-mTouchSlop:deltaX+mTouchSlop;
}else if(yDiff>mTouchSlop){
//表明不是水平滑动,即不判定为SwipeItemLayout的滑动
//但是,可能是下拉刷新SwipeRefreshLayout或者RecyclerView的滑动
//一般的下拉判定,都是yDiff>mTouchSlop,所以,此处这么写不会出问题
//这里这么做以后,如果判定为下拉,就直接close
//不能调用onTouchEvent(),因为它一定返回true
mDragHandleBySuper = true;//super.onInterceptTouchEvent(ev);
super.onTouchEvent(ev);
}
}
touchMode = mCaptureItem.getTouchMode();
if(touchMode== SwipeItemLayout.Mode.DRAG){
mLastMotionX = x;
mLastMotionY = y;
//对capture item进行拖拽
mCaptureItem.trackMotionScroll(deltaX);
}
}else
mDragHandleBySuper = super.onTouchEvent(ev);
if(mDragHandleBySuper && mCaptureItem!=null)
mCaptureItem.close();
return true;
}
case MotionEvent.ACTION_UP:
if(mDragHandleByThis && mCaptureItem!=null/**起始一定不为null*/){
Mode touchMode = mCaptureItem.getTouchMode();
if(touchMode== Mode.DRAG){
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int xVel = (int) velocityTracker.getXVelocity(mActivePointerId);
mCaptureItem.fling(xVel);
}
}else
super.onTouchEvent(ev);
cancel();
return true;
case MotionEvent.ACTION_CANCEL:
if(mCaptureItem!=null)
mCaptureItem.revise();
super.onTouchEvent(ev);
cancel();
return true;
}
return true;
}
void cancel(){
mDragHandleBySuper = false;
mDragHandleByThis = false;
mIsCancelEvent = false;
mActivePointerId = -1;
if(mVelocityTracker!=null){
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
public void closeAllItems(ViewGroup parent){
if(mCaptureItem!=null && mCaptureItem.isOpen())
mCaptureItem.close();
}
}
3.把原来item的布局最外层替换成新加入的SwipeItemLayout
<?xml version="1.0" encoding="utf-8"?>
<SwipeItemLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:id="@+id/ll_driver"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_90"
android:layout_marginTop="@dimen/dp_10"
android:background="@color/white"
android:gravity="center"
android:orientation="horizontal"
android:paddingRight="@dimen/dp_16">
// 略略略略略略略略略略略略略略
</LinearLayout>
//这里是新加入的右滑出的自定义的布局 demo只写了一个删除按钮
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/dp_10">
<Button
android:id="@+id/btn_delete"
android:layout_width="100dp"
android:layout_height="match_parent"
android:background="@drawable/btn_delete"
android:text="删除"
android:textColor="#ffffff"
android:textSize="16sp" />
</LinearLayout>
</SwipeItemLayout>
4.把原来的listView改成SwipeListView
//支持在SmartRefreshLayout里 原来的功能不变
<com.scwang.smartrefresh.layout.SmartRefreshLayout
android:id="@+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srlEnableScrollContentWhenLoaded="true"
android:visibility="gone"
android:layout_above="@+id/btn_confirm"
android:layout_below="@+id/ll_toolbar"
app:srlEnableFooterFollowWhenLoadFinished="true">
//只是把这的listView换了SwipeListView
<SwipeListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f4f4f4"
android:overScrollMode="never"
android:dividerHeight="@dimen/line_height"
android:divider="@color/color_e4e4e4"
tools:listitem="@android:layout/simple_list_item_2" />
</SmartRefreshLayout>
5.原来listview的adapter不变 只需加入自定义控件的事件就好了
RelativeLayout linearLayout = (RelativeLayout) holder.findViewById(R.id.ll_driver);
linearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//原来的item点击事件
}
}
});
Button btnDelete = (Button) holder.findViewById(R.id.btn_delete);
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//自定义的删除事件
delete(driverId);
mAdapter.notifyDataSetInvalidated();
}
});