天天看點

android 仿qq左滑,Android仿QQ清單左滑删除操作

最近學習了如何做一個像QQ的左滑RecyclerView的item顯示選項的,主要是用到Scroller

我們首先建立一個自己的RecyclerView

定義好一些要用的的變量

重寫構造方法,把前兩個構造方法改為如下,使無論如何構造都要執行第三個構造方法

在第三個構造方法裡初始化Scroller

public class LeftSwipeMenuRecyclerView extends RecyclerView {

//置頂按鈕

private TextView tvTop;

//删除按鈕

private TextView tvDelete;

//item相應的布局

private LinearLayout mItemLayout;

//菜單的最大寬度

private int mMaxLength;

//上一次觸摸行為的x坐标

private int mLastX;

//上一次觸摸行為的y坐标

private int mLastY;

//目前觸摸的item的位置

private int mPosition;

//是否在垂直滑動清單

private boolean isDragging;

//item是在否跟随手指移動

private boolean isItemMoving;

//item是否開始自動滑動

private boolean isStartScroll;

//左滑菜單狀态 0:關閉 1:将要關閉 2:将要打開 3:打開

private int mMenuState;

private static int MENU_CLOSED = 0;

private static int MENU_WILL_CLOSED = 1;

private static int MENU_OPEN = 2;

private static int MENU_WILL_OPEN = 3;

//實作彈性滑動,恢複

private Scroller mScroller;

//item的事件監聽

private OnItemActionListener mListener;

public LeftSwipeMenuRecyclerView(Context context) {

this(context, null);

}

public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public LeftSwipeMenuRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

mScroller = new Scroller(context, new LinearInterpolator());

}

重寫onTouchEvent方法

event主要有以下幾個Action

ACTION_DOWN 手指接觸到螢幕

ACTION_MOVE 手指在螢幕滑動

ACTION_UP 手指離開螢幕

一開始肯定要擷取x和y的相對坐标

int x= (int) event.getX();

int y= (int) event.getY();

然後接下來分别處理3個不同的行為

1.ACTION_DOWN

case MotionEvent.ACTION_DOWN:

if (mMenuState == MENU_CLOSED) {

//根據坐标獲得view

View view = findChildViewUnder(x, y);

if (view == null) {

return false;

}

//獲得這個view的ViewHolder

RVAdapter.Holder holder = (RVAdapter.Holder) getChildViewHolder(view);

//獲得這個view的position

mPosition = holder.getAdapterPosition();

//獲得這個view的整個布局

mItemLayout = holder.llLayout;

//獲得這個view的删除按鈕

tvDelete = holder.tvDelete;

//這個view的整個置頂按鈕

tvTop = holder.tvTop;

//兩個按鈕的寬度

mMaxLength = tvDelete.getWidth() + tvTop.getWidth();

//設定删除按鈕點選監聽

tvDelete.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View view) {

mItemLayout.scrollTo(0, 0);

mMenuState =MENU_CLOSED;

mListener.OnItemDelete(mPosition);

}

});

//設定置頂按鈕點選監聽

tvTop.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View view) {

mItemLayout.scrollTo(0, 0);

mMenuState =MENU_CLOSED;

mListener.OnItemTop(mPosition);

}

});

//如果是打開狀态,點選其他就把目前menu關閉掉

} else if (mMenuState == MENU_OPEN) {

mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200);

invalidate();

mMenuState = MENU_CLOSED;

//該點選無效

return false;

} else {

return false;

}

break;

2.ACTION_MOVE

case MotionEvent.ACTION_MOVE:

//計算偏移量

int dx = mLastX - x;

int dy = mLastY - y;

//目前滑動的x

int scrollx = mItemLayout.getScrollX();

if (Math.abs(dx) > Math.abs(dy)) {

isItemMoving = true;

//超出左邊界則始終保持不動

if (scrollx + dx <= 0) {

mItemLayout.scrollTo(0, 0);

//滑動無效

return false;

//超出右邊界則始終保持不動

} else if (scrollx + dx >= mMaxLength) {

mItemLayout.scrollTo(mMaxLength, 0);

//滑動無效

return false;

}

//菜單随着手指移動

mItemLayout.scrollBy(dx, 0);

//如果水準移動距離大于30像素的話,recyclerView不會上下滑動

}else if (Math.abs(dx) > 30){

return true;

}

//如果菜單正在打開就不能上下滑動

if (isItemMoving){

mLastX = x;

mLastY = y;

return true;

}

break;

3.ACTION_UP

case MotionEvent.ACTION_UP:

//手指擡起時判斷是否點選,靜止且有Listener才能點選

if (!isItemMoving && !isDragging && mListener != null) {

mListener.OnItemClick(mPosition);

}

isItemMoving = false;

//等一下要移動的距離

int deltaX = 0;

int upScrollx = mItemLayout.getScrollX();

//滑動距離大于1/2menu長度就自動展開,否則就關掉

if (upScrollx >= mMaxLength / 2) {

deltaX = mMaxLength - upScrollx;

mMenuState = MENU_WILL_OPEN;

} else if (upScrollx < mMaxLength / 2) {

deltaX = -upScrollx;

mMenuState = MENU_WILL_CLOSED;

}

//知道我們為什麼不直接把mMenuState指派為MENU_OPEN或者MENU_CLOSED嗎?因為滑動時有時間的,我們可以在滑動完成時才把狀态改為已經完成

mScroller.startScroll(upScrollx, 0, deltaX, 0, 200);

isStartScroll = true;

//重新整理界面

invalidate();

break;

之後還要在onTouchEvent方法裡重新整理坐标

//隻有更新mLastX,mLastY資料才會準确

mLastX = x;

mLastY = y;

return super.onTouchEvent(e);

因為我們用到了startScroll是以要重寫computeScroll方法

public void computeScroll() {

//判斷scroller是否完成滑動

if (mScroller.computeScrollOffset()) {

mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());

//這個很重要

invalidate();

//如果已經完成就改變狀态

} else if (isStartScroll) {

isStartScroll = false;

if (mMenuState == MENU_WILL_CLOSED) {

mMenuState = MENU_CLOSED;

}

if (mMenuState == MENU_WILL_OPEN) {

mMenuState = MENU_OPEN;

}

}

}

**還要監聽RecyclerView是否在上下滑動

@Override

public void onScrollStateChanged(int state) {

super.onScrollStateChanged(state);

//是否在上下滑動

isDragging = state == SCROLL_STATE_DRAGGING;

}

還要設定Listener

//設定Listener

public void setOnItemActionListener(OnItemActionListener onItemActionListener) {

this.mListener = onItemActionListener;

}

這個Listener是要自己建立的

public interface OnItemActionListener {

void OnItemClick(int position);

void OnItemTop(int position);

void OnItemDelete(int position);

}

最後是點選,置頂,删除在Activity裡的回調

這裡隻展示回調實作部分,我這裡用的List是LinkedList,可以在第一位添加資料

rv.setOnItemActionListener(new OnItemActionListener() {

//點選

@Override

public void OnItemClick(int position) {

Toast.makeText(MainActivity.this,"Click"+position,Toast.LENGTH_SHORT).show();

}

//置頂

@Override

public void OnItemTop(int position) {

//獲得目前位置的内容

String temp =list.get(position);

//移除這個item

list.remove(position);

//把它添加到第一個

list.addFirst(temp);

//更新資料源

adapter.notifyDataSetChanged();

}

//删除

@Override

public void OnItemDelete(int position) {

list.remove(position);

//更新資料源

adapter.notifyDataSetChanged();

}

});

Adapter和布局的代碼太簡單我就不放出來了,大家可以到源碼裡看看有什麼

效果圖

android 仿qq左滑,Android仿QQ清單左滑删除操作

以上就是本文的全部内容,希望對大家的學習有所幫助,也希望大家多多支援找一找教程網。