自定义RecyclerView (具体参考的哪篇文章忘了,如有侵权,请留言)
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.Scroller;
import android.widget.TextView;
import com.anst.library.view.common.BaseViewHolder;
import com.zufang.ui.R;
/**
* Copyright (C), 2018-2018,
* Author:
* Date: 2018/5/22 0022 下午 2:39
* Description: Item 可以侧滑的Recycler
*/
public class SlideItemRecycler extends RecyclerView {
//4种状态,分别为关闭、正在关闭、正在打开、打开
private int status = CLOSE;
public static final int CLOSE = 0;
public static final int CLOSING = 1;
public static final int OPENING = 2;
public static final int OPEN = 3;
//默认的滑动时间
public static final int DEFAULT_TIME = 200;
//滑动速度临界值
public static final int VELOCITY = 100;
private Context mContext;
//检测滑动速度
private VelocityTracker mVelocityTracker;
private Scroller mScroller;
private View mItemView;
private TextView mRightHideTv;
//向左滑动(打开)
private boolean isLeftMoving;
//是否是水平滑动
private boolean isHorMoving;
//是否是垂直滑动
private boolean isVerMoving;
//是否开始滑动
private boolean isStartScroll;
//手指一次滑动在未抬起前,只能是上下滑动或者左右滑动。true表示抬手前在上下移动, false 表示没有移动或者在横向移动
private boolean isOration = false;
//OnTouch点的位置
private int mLastX;
private int mLastY;
//item 的index
private int mPosition;
//删除图片的宽度
private int mMaxLength;
private OnItemClickListener mListener;
public SlideItemRecycler(Context context) {
this(context, null);
}
public SlideItemRecycler(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SlideItemRecycler(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
mScroller = new Scroller(mContext, new LinearInterpolator());
mVelocityTracker = VelocityTracker.obtain();
}
@Override
public boolean onTouchEvent(MotionEvent e) {
mVelocityTracker.addMovement(e);
//获取当前坐标
int x = (int) e.getX();
int y = (int) e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
//item右侧还没打开的状态
if (status == CLOSE) {
//寻找对应坐标点下的V
View view = findChildViewUnder(x, y);
if (view == null) {
return false;
}
//通过baseviewholder获取对应的子View,详情可以看代码
BaseViewHolder viewHolder = (BaseViewHolder) getChildViewHolder(view);
mItemView = viewHolder.getView(R.id.item_layout);
mPosition = viewHolder.getAdapterPosition();
mRightHideTv = viewHolder.getView(R.id.recycler_right_hide_view);
mMaxLength = mRightHideTv.getWidth();
mRightHideTv.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
//返回原点
mItemView.scrollTo(0, 0);
status = CLOSE;
if (mListener != null) {
mListener.onDeleteClick(mPosition);
mListener.setScrollable(true);
}
}
});
//当删除图片已经完全显示的时候
} else if (status == OPEN) {
//从当前view的偏移点mItemView.getScrollX(),位移-mMaxLength长度单位
// 时间DEFAULT_TIMEms,向左移动为正数
mScroller.startScroll(mItemView.getScrollX(), 0, -mMaxLength, 0, DEFAULT_TIME);
//刷新下一帧动画
invalidate();
status = CLOSE;
isHorMoving = false; // 此处点击就把删除部分关闭了
//设置recycler是否可以上下滑动
if (mListener != null) {
mListener.setScrollable(true);
}
return false;
} else {
return false;
}
break;
case MotionEvent.ACTION_MOVE:
//获取上次的落点与当前的坐标之间的差值
int dx = mLastX - x;
int dy = mLastY - y;
int scrollX = mItemView.getScrollX();
if (Math.abs(dx) <= Math.abs(dy)) {
isOration = true;
}
//水平滑动距离大于垂直距离 并且没有在上下移动
if (Math.abs(dx) > Math.abs(dy) && !isVerMoving && !isOration) {
if (mListener != null) {
mListener.setScrollable(false);
}
//设置recycler是否可以上下滑动
isHorMoving = true;
//向左滑动,直至显示删除图片,向左滑动的最大距离不超过删除图片的宽度
if (scrollX + dx >= mMaxLength) {
mItemView.scrollTo(mMaxLength, 0);
return true;
//向右滑动,直至删除图片不显示,向右滑动的最大距离不超过初始位置
} else if (scrollX + dx <= 0) {
mItemView.scrollTo(0, 0);
return true;
}
//如果在图片还未完全显示的状态下,那么手指滑动多少,图片就移动多少
mItemView.scrollBy(dx, 0);
}
break;
case MotionEvent.ACTION_UP:
if (!isHorMoving && !isVerMoving && mListener != null) {
mListener.onItemClick(mItemView, mPosition);
}
if (!isVerMoving && !isOration) {
mVelocityTracker.computeCurrentVelocity(1000);//计算手指滑动的速度
float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左为负)
float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度
int upScrollX = mItemView.getScrollX();
int deltaX = 0;
//向右滑动速度为正数
//滑动速度快的状态下抬起手指,计算所需偏移量
if (Math.abs(xVelocity) > Math.abs(yVelocity) && Math.abs(xVelocity) >= VELOCITY) {
//向右隐藏
if (xVelocity >= VELOCITY) {
deltaX = -upScrollX;
status = CLOSING;
isHorMoving = false;
} else if (xVelocity <= -VELOCITY) {
deltaX = mMaxLength - upScrollX;
status = OPENING;
}
//滑动速度慢的状态下抬起手指,如果滑动距离大于1/2的图片宽度,计算偏移量
//不够的话恢复原点
} else {
if (upScrollX >= mMaxLength / 2) {
deltaX = mMaxLength - upScrollX;
status = OPENING;
} else {
deltaX = -upScrollX;
status = CLOSING;
isHorMoving = false;
}
}
mScroller.startScroll(upScrollX, 0, deltaX, 0, DEFAULT_TIME);
isStartScroll = true;
invalidate();
mVelocityTracker.clear();
}
break;
}
mLastX = x;
mLastY = y;
isOration = false;
return super.onTouchEvent(e);
}
@Override
public void computeScroll() {
//滚动是否完成,true表示还未完成
if (mScroller.computeScrollOffset()) {
mItemView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
//有滑动,并且在滑动结束的时候
} else if (isStartScroll) {
isStartScroll = false;
if (status == CLOSING) {
status = CLOSE;
//设置recycler是否可以上下滑动
if (mListener != null) {
mListener.setScrollable(true);
}
}
if (status == OPENING)
status = OPEN;
}
}
@Override
protected void onDetachedFromWindow() {
mVelocityTracker.recycle();
super.onDetachedFromWindow();
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
isVerMoving = state == SCROLL_STATE_DRAGGING;
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mListener = listener;
}
}
Adapter 的ItemView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.anst.library.entity.common.HouseListItemView
android:id="@+id/item_houseList"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:id="@+id/recycler_right_hide_view"
android:layout_width="80dp"
android:layout_height="match_parent"
android:background="#88ff0000"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="@dimen/dimen_13sp"
android:text="@string/str_cancel_favor"/>
</LinearLayout>
</RelativeLayout>
网友评论