Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 使用RecylerView完成拖動排序高仿qq側滑刪除功能

使用RecylerView完成拖動排序高仿qq側滑刪除功能

編輯:關於Android編程

 最近使用到Recylerview完成拖動排序,側滑刪除,在此記錄一下。

需要使用到:ItemTouchHelper.Callback這個類。

效果圖:

在有RecylerView的Activity中,除了設置Adapter還需要做的事情有:

MyItemTouchHelperCallback callback = new MyItemTouchHelperCallback(adapter); //此類繼承ItemTouchHelper.Callback,這是幫助處理RecylerView拖動側滑操作的輔助類 
ItemTouchHelper helper = new ItemTouchHelper(callback); //用上面實例化的callback實例化一個ItemTouchHelper對象。套路代碼,沒啥好說的,固定做法 
helper.attachToRecyclerView(recyclerView); //讓help幫助處理recylerview的滑動,側滑操作

Activity中的操作就這麼簡單。

接下來定義一個接口,這個接口是為了解除耦合,因為我看到有一些文章在activity中處理了onMove和onSwipe,抽象出來更好理解。

public interface OnMoveAndSwipeListener { 
public boolean onItemMove(int fromPosition, int toPosition); //注意返回boolean哦 
public void onItemDismiss(int position); 
}

在RecylerView的Adapter中實現此接口,

復寫上面的兩個方法,

@Override 
public boolean onItemMove(int fromPosition, int toPosition) { 
if (fromPosition < toPosition) { 
//往下移動時,做數據交換 
for (int i = fromPosition; i < toPosition; i++) { 
Collections.swap(list,i,i+1); 
} 
}else{ 
//往上移動,做數據交換 
for (int i = fromPosition; i >toPosition ; i--) { 
Collections.swap(list,i,i-1); 
} 
} 
notifyItemMoved(fromPosition,toPosition); 
return true; 
} 
@Override 
public void onItemDismiss(int position) { 
//此例沒有對側滑做操作,如果需要就在此模仿onItemMove方法,刪除對應位置的數據,並且刷新界面就可以了 
}

這樣Adapter的工作也就完成了,一樣也很簡單,都有固定的套路,注意大家看到的demo都是有個默認的動畫,這個動畫效果是你在設置RecylerView時,recylerview.setItemAnimator(參數);設置進去的,如果你沒有調用此方法,則就是默認動畫效果。

除了設置Adapter還需要做的事情有:

寫一個類繼承ItemTouchHelper.Callback,這就是最後一步了,也是本文最開始在Activity中實例化的類,

代碼也不多:

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback { 
MyAdapter adapter; 
public MyItemTouchHelperCallback(MyAdapter adapter) { 
this.adapter = adapter; 
} 
@Override 
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
//復寫此方法用來設置我需要處理哪些操作 
//我要處理上下拖動,就設置up down,如果是gridview類型的recylerview,up,down,left,right都可以處理 
final int moveMode = ItemTouchHelper.UP | ItemTouchHelper.DOWN; 
//本例沒有處理側滑,如果需要處理側滑,就把注釋取消掉 
//final int swipeMode = ItemTouchHelper.START | ItemTouchHelper.END; 
Log.e("getMovementFlags","getMovementFlags"); 
return makeMovementFlags(moveMode, 0);//不處理什麼,就傳0 
} 
@Override 
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 
//當你拖動時就會觸發此回調,然後調用在adapter中復寫的onItemMove方法,去交換數據 
return adapter.onItemMove(viewHolder.getAdapterPosition(),target.getAdapterPosition()); 
} 
@Override 
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 
//如果你要處理側滑就取消注釋,邏輯和上面的onMove一樣 
// adapter.onItemDismiss(viewHolder.getAdapterPosition()); 
} 
@Override 
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 
//此方法在你選中一個item拖動時觸發,所以你可以在這裡給選中的item設置一個背景色,用於高亮提示你選中了這個背景色 
super.onSelectedChanged(viewHolder, actionState); 
if (actionState!= ItemTouchHelper.ACTION_STATE_IDLE){ 
viewHolder.itemView.setBackgroundColor(Color.LTGRAY); 
} 
} 
@Override 
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
//因為你設置了背景色,所以在你不選中的時候,要取消掉這個背景色。 
super.clearView(recyclerView, viewHolder); 
viewHolder.itemView.setBackgroundColor(0); 
} 
}

到此為止,一個簡單的拖動和側滑就完成了,其實拖動和側滑的邏輯都是一樣的,按著上面的步驟來,效果就出來了。

上面只是一個簡單的效果。把上面的效果實現了,接下來看更進階一點的效果:

RecycleViewSwipeDismiss

要做到上述的效果,先說一下上面的邏輯:

首先他的每個Item的布局是兩層:

<?xml version="1.0" encoding="utf-8"?> 
<!--背景view,用於提示用戶操作結果--> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/rl_background" 
android:layout_width="match_parent" 
android:layout_height="wrap_content"> 
<ImageView 
android:id="@+id/iv_done" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_centerVertical="true" 
android:layout_marginLeft="16dp" 
android:layout_marginStart="16dp" 
android:src="@mipmap/bt_ic_done_white_24" /> 
<ImageView 
android:id="@+id/iv_schedule" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_alignParentRight="true" 
android:layout_centerVertical="true" 
android:layout_marginEnd="16dp" 
android:layout_marginRight="16dp" 
android:src="@mipmap/bt_ic_schedule_white_24" /> 
<!--滑動操作的view--> 
<LinearLayout 
android:id="@+id/ll_item" 
android:layout_width="match_parent" 
android:layout_height="64dp" 
android:background="@android:color/white" 
android:gravity="center_vertical" 
android:orientation="vertical" 
android:paddingLeft="16dp" 
android:paddingRight="16dp"> 
<TextView 
android:id="@+id/tv_item" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:textAppearance="?android:attr/textAppearanceMedium" 
tools:text="Item" /> 
</LinearLayout> 
<View 
android:layout_width="match_parent" 
android:layout_height="1dp" 
android:layout_below="@id/ll_item" 
android:background="#B2B2b2" /> 
</RelativeLayout>

原理:全屏的linearlayout負責側滑效果,而根布局是有顏色有圖片的那一層,因為linearlayout被滑走了,所以根布局以及上面的圖片就出來了。

需要在MyItemTouchHelperCallback中重新復寫的幾個方法,以及多復寫的幾個方法:

<span > </span> @Override 
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 
// 釋放View時回調,清除背景顏色,隱藏圖標 
// 默認是操作ViewHolder的itemView,這裡調用ItemTouchUIUtil的clearView方法傳入指定的view 
getDefaultUIUtil().clearView(((SampleAdapter.ItemViewHolder) viewHolder).vItem); 
((SampleAdapter.ItemViewHolder) viewHolder).vBackground.setBackgroundColor(Color.TRANSPARENT); 
((SampleAdapter.ItemViewHolder) viewHolder).ivSchedule.setVisibility(View.GONE); 
((SampleAdapter.ItemViewHolder) viewHolder).ivDone.setVisibility(View.GONE); 
} 
@Override 
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { 
// 當viewHolder的滑動或拖拽狀態改變時回調 
if (viewHolder != null) { 
// 默認是操作ViewHolder的itemView,這裡調用ItemTouchUIUtil的clearView方法傳入指定的view 
getDefaultUIUtil().onSelected(((SampleAdapter.ItemViewHolder) viewHolder).vItem); 
} 
} 
@Override 
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { 
// ItemTouchHelper的onDraw方法會調用該方法,可以使用Canvas對象進行繪制,繪制的圖案會在RecyclerView的下方 
// 默認是操作ViewHolder的itemView,這裡調用ItemTouchUIUtil的clearView方法傳入指定的view 
getDefaultUIUtil().onDraw(c, recyclerView, ((SampleAdapter.ItemViewHolder) viewHolder).vItem, dX, dY, actionState, isCurrentlyActive); 
if (dX > 0) { // 向左滑動是的提示 
((SampleAdapter.ItemViewHolder) viewHolder).vBackground.setBackgroundResource(R.color.colorDone); 
((SampleAdapter.ItemViewHolder) viewHolder).ivDone.setVisibility(View.VISIBLE); 
((SampleAdapter.ItemViewHolder) viewHolder).ivSchedule.setVisibility(View.GONE); 
} 
if (dX < 0) { // 向右滑動時的提示 
((SampleAdapter.ItemViewHolder) viewHolder).vBackground.setBackgroundResource(R.color.colorSchedule); 
((SampleAdapter.ItemViewHolder) viewHolder).ivSchedule.setVisibility(View.VISIBLE); 
((SampleAdapter.ItemViewHolder) viewHolder).ivDone.setVisibility(View.GONE); 
} 
} 
@Override 
public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { 
// ItemTouchHelper的onDrawOver方法會調用該方法,可以使用Canvas對象進行繪制,繪制的圖案會在RecyclerView的上方 
// 默認是操作ViewHolder的itemView,這裡調用ItemTouchUIUtil的clearView方法傳入指定的view 
getDefaultUIUtil().onDrawOver(c, recyclerView, ((SampleAdapter.ItemViewHolder) viewHolder).vItem, dX, dY, actionState, isCurrentlyActive); 
} 
});

用getDefaultUIUtil()的方法指定滑動操作的是linearlayout,所以每次被滑走的只有linearlayout。其他的操作都是一樣的。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved