先看效果:
可側滑刪除修改的的 SlideRecyclerView ,繼承Recycler View,重寫 onTouchEvent方法
public class SlideRecyclerView extends RecyclerView {
private String TAG = "SlideRecyclerView";
private int mMaxScrollWidth;
private boolean isRlvScrolling;
private int lastRlvScrollState;
private boolean isItemStartScroll;
private VelocityTracker mVelocityTracker;
private Scroller mScroller;
private int mItemState;//0:關閉,1:將要關閉,2:將要打開,3:打開
private View mItemLayout;
private int downX=0;
private int downY=0;
private boolean isItemEnterMoving;
private int mPosition;
private int lastX ;
private int lastY ;
private OnItemClickListener onItemClickListener;
private int lastOperatePositon;
private boolean isMoved;
private int deleteWidth;
private int updateWidth;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
public SlideRecyclerView(Context context) {
super(context);
init();
}
public SlideRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public SlideRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init(){
mVelocityTracker = VelocityTracker.obtain();
mScroller = new Scroller(getContext());
}
@Override
public boolean onTouchEvent(MotionEvent e) {
mVelocityTracker.addMovement(e);
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
isMoved = false;
isItemEnterMoving = false;
downX = (int) (e.getX() + 0.5f);
downY = (int) (e.getY() + 0.5f);
lastX = downX;
lastY = downY;
View view = findChildViewUnder(downX, downY);
if (view == null) {
return false;
}
ViewHolder viewHolder = getChildViewHolder(view);
//首先獲取位置
mPosition = viewHolder.getAdapterPosition();
//關閉狀態
if (mItemState == 0) {
mItemLayout = view;
updateWidth = mItemLayout.findViewById(R.id.view_item_update).getWidth();
deleteWidth = mItemLayout.findViewById(R.id.view_item_delete).getWidth();
mMaxScrollWidth = updateWidth + deleteWidth;
//在這裏其他狀態統統關閉,不然會導致還沒關閉就出現點擊事件(h)
} else if (mItemState == 3 || mItemState == 2 || mItemState == 1) {
//如果點擊的不是上一個,就關閉上一個
if (lastOperatePositon != mPosition){
mScroller.startScroll(mItemLayout.getScrollX(), 0, /*-mMaxScrollWidth*/ 0 -mItemLayout.getScrollX(), 0, 400);
invalidate();
mItemState = 0;
return false;//防止走UP 事件,防止響應點擊事件
}else {
//return true 繼續調用onTouchEvent
return true;
}
}
break;
case MotionEvent.ACTION_MOVE:
int currX = (int) (e.getX() + 0.5f);
int currY = (int) (e.getY() + 0.5f);
//移動距離
int moveX = currX - downX;
int moveY = currY - downY;
int dx = currX - lastX;
int dy = currY - lastY;
//移動了就不響應點擊事件
if (Math.abs(moveX) >16 || Math.abs(moveY) > 16){
isMoved = true;
}
if (Math.abs(moveX) > Math.abs(moveY)) {
isItemEnterMoving = true;
}
int scrollX = mItemLayout.getScrollX();
Log.d(TAG, "onTouchEvent: @@@@@@ ACTION_MOVE isRlvScrolling = " + isRlvScrolling);
Log.d(TAG, "onTouchEvent: @@@@@@ ACTION_MOVE isItemEnterMoving= " + isItemEnterMoving );
if(isItemEnterMoving && !isRlvScrolling){
if (scrollX - dx >= mMaxScrollWidth) {//防止左滑過多
mItemLayout.scrollTo(mMaxScrollWidth, 0);
lastX = currX;
lastY = currY;
return true;
} else if (scrollX - dx <= 0) {//防止右滑過多
mItemLayout.scrollTo(0, 0);
lastX = currX;
lastY = currY;
return true;
}
Log.d(TAG, "onTouchEvent: scrollX = " + scrollX );
Log.d(TAG, "onTouchEvent: -dx = " + (-dx ) );
mItemLayout.scrollBy(-dx, 0);//item跟隨手指滑動
Log.d(TAG, "onTouchEvent: scrollX New = " + mItemLayout.getScrollX() );
lastX = currX;
lastY = currY;
return true;
}
break;
case MotionEvent.ACTION_UP:
lastOperatePositon = mPosition;
if (isRlvScrolling){
return super.onTouchEvent(e);
}
mVelocityTracker.computeCurrentVelocity(1000);//計算手指滑動的速度
float xVelocity = mVelocityTracker.getXVelocity();//水平方向速度(向左爲負)
// float yVelocity = mVelocityTracker.getYVelocity();//垂直方向速度
int deltaX = 0;
int upScrollX = mItemLayout.getScrollX();
if (Math.abs(xVelocity) > 100 /*&& Math.abs(xVelocity) > Math.abs(yVelocity)*/) {
if (xVelocity <= -100) {//左滑速度大於100,則打開item
deltaX = mMaxScrollWidth - upScrollX;
mItemState = 2;
} else if (xVelocity > 100) {//右滑速度大於100,則關閉item
deltaX = -upScrollX;
mItemState = 1;
}
} else {
if (upScrollX >= mMaxScrollWidth / 2) {//item的左滑動距離大於側滑View寬度的一半,則打開item
deltaX = mMaxScrollWidth - upScrollX;
mItemState = 2;
} else if (upScrollX < mMaxScrollWidth / 2) {//否則隱藏
deltaX = -upScrollX;
mItemState = 1;
}
}
//item自動滑動到指定位置
mScroller.startScroll(upScrollX, 0, deltaX, 0, 400);
isItemStartScroll = true;
invalidate();
mVelocityTracker.clear();
//點擊事件
int x = (int) (e.getX()+0.5f);
//&& isMoved 移動的情況下不響應點擊事件
if (null != onItemClickListener && !isMoved){
if (0 == mItemLayout.getScrollX()){
onItemClickListener.onItemClick(mItemLayout,mPosition);
}else if (mMaxScrollWidth == mItemLayout.getScrollX()){
if (x >=0 && x < getWidth() - mMaxScrollWidth){
onItemClickListener.onItemClick(mItemLayout,mPosition);
}else if (x>= getWidth() - mMaxScrollWidth && x < getWidth() - deleteWidth){
onItemClickListener.onUpdateClick(mItemLayout,mPosition);
}else if (x >= getWidth() - deleteWidth && x<=getWidth()){
onItemClickListener.onDeleteClick(mItemLayout,mPosition);
}
}
}
break;
}
return super.onTouchEvent(e);
}
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
} else if (isItemStartScroll) {
isItemStartScroll = false;
if (mItemState == 1) {
mItemState = 0;
}
if (mItemState == 2) {
mItemState = 3;
}
}
}
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
isRlvScrolling = (state == SCROLL_STATE_DRAGGING && lastRlvScrollState == SCROLL_STATE_IDLE);
lastRlvScrollState= state;
}
public interface OnItemClickListener {
void onDeleteClick(View itemView, int position);
void onUpdateClick(View itemView, int position);
void onItemClick(View itemView, int position);
}
}
item 佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#660000ff"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="100dp">
<TextView
android:id="@+id/textview"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/view_item_update"
android:textSize="20dp"
android:textColor="#ffffff"
android:text="修改"
android:gravity="center"
android:background="@color/colorPrimaryDark"
android:layout_width="80dp"
android:layout_height="match_parent" />
<TextView
android:id="@+id/view_item_delete"
android:textSize="20dp"
android:text="刪除"
android:gravity="center"
android:textColor="#ffffff"
android:background="@color/colorAccent"
android:layout_width="80dp"
android:layout_height="match_parent" />
</LinearLayout>
使用:
佈局文件中使用
<com.example.myapplication1.view.SlideRecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.myapplication1.view.SlideRecyclerView>
點擊事件:
recyclerview.setOnItemClickListener(new SlideRecyclerView.OnItemClickListener() {
@Override
public void onDeleteClick(View itemView, int position) {
Toast.makeText(CustomViewActivity.this,"刪除",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpdateClick(View itemView, int position) {
Toast.makeText(CustomViewActivity.this,"修改",Toast.LENGTH_SHORT).show();
}
@Override
public void onItemClick(View itemView, int position) {
Toast.makeText(CustomViewActivity.this,"內容",Toast.LENGTH_SHORT).show();
}
});