Android仿QQ列表左滑刪除操作
最近學(xué)習(xí)了如何做一個(gè)像QQ的左滑RecyclerView的item顯示選項(xiàng)的,主要是用到Scroller
我們首先新建一個(gè)自己的RecyclerView
定義好一些要用的的變量
重寫構(gòu)造方法,把前兩個(gè)構(gòu)造方法改為如下,使無論如何構(gòu)造都要執(zhí)行第三個(gè)構(gòu)造方法
在第三個(gè)構(gòu)造方法里初始化Scroller
public class LeftSwipeMenuRecyclerView extends RecyclerView {
//置頂按鈕
private TextView tvTop;
//刪除按鈕
private TextView tvDelete;
//item相應(yīng)的布局
private LinearLayout mItemLayout;
//菜單的最大寬度
private int mMaxLength;
//上一次觸摸行為的x坐標(biāo)
private int mLastX;
//上一次觸摸行為的y坐標(biāo)
private int mLastY;
//當(dāng)前觸摸的item的位置
private int mPosition;
//是否在垂直滑動(dòng)列表
private boolean isDragging;
//item是在否跟隨手指移動(dòng)
private boolean isItemMoving;
//item是否開始自動(dòng)滑動(dòng)
private boolean isStartScroll;
//左滑菜單狀態(tài) 0:關(guān)閉 1:將要關(guān)閉 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;
//實(shí)現(xiàn)彈性滑動(dòng),恢復(fù)
private Scroller mScroller;
//item的事件監(jiān)聽
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主要有以下幾個(gè)Action
- ACTION_DOWN 手指接觸到屏幕
- ACTION_MOVE 手指在屏幕滑動(dòng)
- ACTION_UP 手指離開屏幕
一開始肯定要獲取x和y的相對(duì)坐標(biāo)
int x= (int) event.getX(); int y= (int) event.getY();
然后接下來分別處理3個(gè)不同的行為
1.ACTION_DOWN
case MotionEvent.ACTION_DOWN:
if (mMenuState == MENU_CLOSED) {
//根據(jù)坐標(biāo)獲得view
View view = findChildViewUnder(x, y);
if (view == null) {
return false;
}
//獲得這個(gè)view的ViewHolder
RVAdapter.Holder holder = (RVAdapter.Holder) getChildViewHolder(view);
//獲得這個(gè)view的position
mPosition = holder.getAdapterPosition();
//獲得這個(gè)view的整個(gè)布局
mItemLayout = holder.llLayout;
//獲得這個(gè)view的刪除按鈕
tvDelete = holder.tvDelete;
//這個(gè)view的整個(gè)置頂按鈕
tvTop = holder.tvTop;
//兩個(gè)按鈕的寬度
mMaxLength = tvDelete.getWidth() + tvTop.getWidth();
//設(shè)置刪除按鈕點(diǎn)擊監(jiān)聽
tvDelete.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mItemLayout.scrollTo(0, 0);
mMenuState =MENU_CLOSED;
mListener.OnItemDelete(mPosition);
}
});
//設(shè)置置頂按鈕點(diǎn)擊監(jiān)聽
tvTop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mItemLayout.scrollTo(0, 0);
mMenuState =MENU_CLOSED;
mListener.OnItemTop(mPosition);
}
});
//如果是打開狀態(tài),點(diǎn)擊其他就把當(dāng)前menu關(guān)閉掉
} else if (mMenuState == MENU_OPEN) {
mScroller.startScroll(mItemLayout.getScrollX(), 0, -mMaxLength, 0, 200);
invalidate();
mMenuState = MENU_CLOSED;
//該點(diǎn)擊無效
return false;
} else {
return false;
}
break;
2.ACTION_MOVE
case MotionEvent.ACTION_MOVE:
//計(jì)算偏移量
int dx = mLastX - x;
int dy = mLastY - y;
//當(dāng)前滑動(dòng)的x
int scrollx = mItemLayout.getScrollX();
if (Math.abs(dx) > Math.abs(dy)) {
isItemMoving = true;
//超出左邊界則始終保持不動(dòng)
if (scrollx + dx <= 0) {
mItemLayout.scrollTo(0, 0);
//滑動(dòng)無效
return false;
//超出右邊界則始終保持不動(dòng)
} else if (scrollx + dx >= mMaxLength) {
mItemLayout.scrollTo(mMaxLength, 0);
//滑動(dòng)無效
return false;
}
//菜單隨著手指移動(dòng)
mItemLayout.scrollBy(dx, 0);
//如果水平移動(dòng)距離大于30像素的話,recyclerView不會(huì)上下滑動(dòng)
}else if (Math.abs(dx) > 30){
return true;
}
//如果菜單正在打開就不能上下滑動(dòng)
if (isItemMoving){
mLastX = x;
mLastY = y;
return true;
}
break;
3.ACTION_UP
case MotionEvent.ACTION_UP:
//手指抬起時(shí)判斷是否點(diǎn)擊,靜止且有Listener才能點(diǎn)擊
if (!isItemMoving && !isDragging && mListener != null) {
mListener.OnItemClick(mPosition);
}
isItemMoving = false;
//等一下要移動(dòng)的距離
int deltaX = 0;
int upScrollx = mItemLayout.getScrollX();
//滑動(dòng)距離大于1/2menu長(zhǎng)度就自動(dòng)展開,否則就關(guān)掉
if (upScrollx >= mMaxLength / 2) {
deltaX = mMaxLength - upScrollx;
mMenuState = MENU_WILL_OPEN;
} else if (upScrollx < mMaxLength / 2) {
deltaX = -upScrollx;
mMenuState = MENU_WILL_CLOSED;
}
//知道我們?yōu)槭裁床恢苯影裮MenuState賦值為MENU_OPEN或者M(jìn)ENU_CLOSED嗎?因?yàn)榛瑒?dòng)時(shí)有時(shí)間的,我們可以在滑動(dòng)完成時(shí)才把狀態(tài)改為已經(jīng)完成
mScroller.startScroll(upScrollx, 0, deltaX, 0, 200);
isStartScroll = true;
//刷新界面
invalidate();
break;
之后還要在onTouchEvent方法里刷新坐標(biāo)
//只有更新mLastX,mLastY數(shù)據(jù)才會(huì)準(zhǔn)確
mLastX = x;
mLastY = y;
return super.onTouchEvent(e);
因?yàn)槲覀冇玫搅藄tartScroll所以要重寫computeScroll方法
public void computeScroll() {
//判斷scroller是否完成滑動(dòng)
if (mScroller.computeScrollOffset()) {
mItemLayout.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//這個(gè)很重要
invalidate();
//如果已經(jīng)完成就改變狀態(tài)
} else if (isStartScroll) {
isStartScroll = false;
if (mMenuState == MENU_WILL_CLOSED) {
mMenuState = MENU_CLOSED;
}
if (mMenuState == MENU_WILL_OPEN) {
mMenuState = MENU_OPEN;
}
}
}
**還要監(jiān)聽RecyclerView是否在上下滑動(dòng)
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
//是否在上下滑動(dòng)
isDragging = state == SCROLL_STATE_DRAGGING;
}
還要設(shè)置Listener
//設(shè)置Listener
public void setOnItemActionListener(OnItemActionListener onItemActionListener) {
this.mListener = onItemActionListener;
}
這個(gè)Listener是要自己新建的
public interface OnItemActionListener {
void OnItemClick(int position);
void OnItemTop(int position);
void OnItemDelete(int position);
}
最后是點(diǎn)擊,置頂,刪除在Activity里的回調(diào)
這里只展示回調(diào)實(shí)現(xiàn)部分,我這里用的List是LinkedList,可以在第一位添加數(shù)據(jù)
rv.setOnItemActionListener(new OnItemActionListener() {
//點(diǎn)擊
@Override
public void OnItemClick(int position) {
Toast.makeText(MainActivity.this,"Click"+position,Toast.LENGTH_SHORT).show();
}
//置頂
@Override
public void OnItemTop(int position) {
//獲得當(dāng)前位置的內(nèi)容
String temp =list.get(position);
//移除這個(gè)item
list.remove(position);
//把它添加到第一個(gè)
list.addFirst(temp);
//更新數(shù)據(jù)源
adapter.notifyDataSetChanged();
}
//刪除
@Override
public void OnItemDelete(int position) {
list.remove(position);
//更新數(shù)據(jù)源
adapter.notifyDataSetChanged();
}
});
Adapter和布局的代碼太簡(jiǎn)單我就不放出來了,大家可以到源碼里看看有什么
效果圖

源碼地址:https://github.com/jkgeekJack/SlideLeftMenuRecyclerView
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android高仿QQ6.0側(cè)滑刪除實(shí)例代碼
- 詳解Android中實(shí)現(xiàn)ListView左右滑動(dòng)刪除條目的方法
- android RecyclerView側(cè)滑菜單,滑動(dòng)刪除,長(zhǎng)按拖拽,下拉刷新上拉加載
- Android仿微信滑動(dòng)彈出編輯、刪除菜單效果、增加下拉刷新功能
- Android實(shí)現(xiàn)左滑刪除列表功能
- Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng)
- Android使用CardView作為RecyclerView的Item并實(shí)現(xiàn)拖拽和左滑刪除
- Android 滑動(dòng)監(jiān)聽RecyclerView線性流+左右劃刪除+上下移動(dòng)
- Android開發(fā)中模仿qq列表信息滑動(dòng)刪除功能
- Android?Recyclerview實(shí)現(xiàn)左滑刪除功能
相關(guān)文章
Android利用Palette實(shí)現(xiàn)提取圖片顏色
Palette是一個(gè)類似調(diào)色板的工具類,根據(jù)傳入的bitmap,提取出主體顏色,使得圖片和顏色更加搭配,界面更協(xié)調(diào)。本文將詳解如何利用Palette實(shí)現(xiàn)提取圖片顏色,需要的可以參考一下2022-03-03
Android 實(shí)現(xiàn)自定義圓形進(jìn)度條的實(shí)例代碼
進(jìn)度條在Android中教程使用到,本文章向大家介紹一下Android自定義圓形進(jìn)度條實(shí)現(xiàn)代碼,需要的朋友可以參考一下。2016-11-11
幾個(gè)Android編程時(shí)需要注意的 web 問題
這篇文章主要介紹了幾個(gè)Android編程時(shí)需要注意的 web 問題,需要的朋友可以參考下2014-12-12
解決Android Studio突然不顯示logcat日志的問題
這篇文章主要介紹了解決Android Studio突然不顯示logcat日志的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04
Android系統(tǒng)添加Linux驅(qū)動(dòng)
今天小編就為大家分享一篇關(guān)于Android系統(tǒng)添加Linux驅(qū)動(dòng)的文章,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10

