前言:
專案原始碼下載地址:download.csdn.net/detail/mtx_…
此篇主要是通過自動以RecyclerView,同過scrollTo()、Scroller來實現左劃刪除功能。
1.基礎知識引入
scrollTo(int x,inty):
它是View中的方法,可以對View中的內容進行滾動,強調一下滑動的是view的“內容”,scrollTo()是讓View相對於初始的位置滾動某段距離
RecyclerView實現左劃刪除
首選我來看Item的佈局檔案Recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/item_root"
>
<TextView
android:id="@+id/item_text"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_gravity="center"
android:gravity="center"
android:text="text" />
<TextView
android:id="@+id/item_del"
android:layout_width="100dp"
android:layout_height="fill_parent"
android:background="#EE2C2C"
android:text="刪除"
android:textSize="25dp"
android:gravity="center" />
</LinearLayout>複製程式碼
item有兩個水平的textView檔案組成,第一個TextView是我們正常顯示的Item,它的寬度佔滿螢幕,第二TextView就是我們的刪除按鈕,它被隱藏在螢幕之外。下面在看看Adapter部分CustomAdapter.java。
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private List<String> mDatas;
public CustomAdapter(List<String> mDatas, Context mContext) {
this.mDatas = mDatas;
}
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
return new CustomViewHolder(view);
}
@Override
public void onBindViewHolder(final CustomViewHolder holder, final int position) {
holder.textView.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
class CustomViewHolder extends RecyclerView.ViewHolder {
TextView textView;
TextView deleteView;
public CustomViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.item_text);
deleteView = (TextView) itemView.findViewById(R.id.item_del);
}
}
}複製程式碼
這個比較簡單,沒啥可說的,下面我來來看看我的重點部分自定義的CustomRecyclerView類的實現
public class CustomRecyclerView extends RecyclerView{
//item的根佈局
private LinearLayout itemRoot;
//上一次滑動的Item根佈局
private LinearLayout itemRootLast;
//上次X軸的滑動座標
private int mlastX = 0;
//上次Y軸的滑動座標
private int mlastY = 0;
//滑動的最大距離
private final int MAX_WIDTH = 100;
private Context mContext;
private Scroller mScroller;
public CustomRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mContext = context;
mScroller = new Scroller(context, new LinearInterpolator(context, null));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int maxLength = dipToPx(mContext, MAX_WIDTH);
int x = (int) event.getX();
int y = (int) event.getY();
final int position;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
//恢復上一次側滑的ITEM
if(itemRootLast !=null){
itemRootLast.scrollTo(0, 0);
invalidate();
}
//根據點選的座標獲取那個Item被點選了
View view = findChildViewUnder(x, y);
if(view == null){
return false;
}
final CustomAdapter.CustomViewHolder viewHolder = (CustomAdapter.CustomViewHolder) getChildViewHolder(view);
itemRootLast = itemRoot = (LinearLayout) viewHolder.textView.getParent();
position= viewHolder.getAdapterPosition();
if(mOnItemClickListener !=null){
viewHolder.deleteView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
mOnItemClickListener.onClick(viewHolder.itemView,position);
}
});
}
}
break;
case MotionEvent.ACTION_MOVE: {
if(itemRoot ==null){
return false;
}
if( Math.abs(mlastX -x)>0 && Math.abs(mlastX -x) > Math.abs(mlastY-y)){
int scrollX = itemRoot.getScrollX();
int newScrollX = scrollX + mlastX - x;
if (newScrollX < 0) {
newScrollX = 0;
} else if (newScrollX > maxLength) {
newScrollX = maxLength;
}
itemRoot.scrollTo(newScrollX, 0);
}
}
break;
case MotionEvent.ACTION_UP: {
if(itemRoot ==null){
return false;
}
int scrollX = itemRoot.getScrollX();
int newScrollX = scrollX + mlastX - x;
if (scrollX > maxLength / 2) {
newScrollX = maxLength;
} else {
newScrollX = 0;
}
mScroller.startScroll(scrollX, 0, newScrollX - scrollX, 0);
invalidate();
}
break;
}
mlastX = x;
mlastY = y;
return super.onTouchEvent(event);
}
private int dipToPx(Context context, int dip) {
return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
itemRoot.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
if(itemRootLast !=null){
itemRootLast.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
}
}
invalidate();
}
private OnItemClickListener mOnItemClickListener;
public interface OnItemClickListener{
void onClick(View view,int position);
}
public void setOnItemClickListenre(OnItemClickListener mOnItemClickListener){
this.mOnItemClickListener = mOnItemClickListener;
}
}複製程式碼
我來來詳細看一下上面的程式碼:
首選在MotionEvent.ACTION_DOWN事件發生時,如果上次有Item已經側滑出了,這裡就讓它恢復正常的顯示,接著看
我們通過findChildViewUnder(x, y)方法來實現根據當前點選的座標值,得到被點選的Item的view,這一步是很關鍵的,接著我們通過剛才得到view獲取到我們的viewHolder物件,拿到它我們就好辦了,我們就可以得到點選Item的position等。
我們在MotionEvent.ACTION_MOVE事件中去根據手指滑動的距離來實時處理View的滑動
MotionEvent.ACTION_UP事件中,如果此時滑動的距離大於最大滑動距離的一半,我們就讓整個按鈕都滑動出來,反之我就讓它恢復原來的狀態.
刪除按鈕監聽在ACTION_DOWN事件中繫結監聽事件即可,監聽介面如下
我們在MainActivity中實現給就可就Ok了
專案原始碼下載地址:download.csdn.net/detail/mtx_…