溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android如何使用RecycleView實(shí)現(xiàn)拖拽交換item位置

發(fā)布時(shí)間:2020-07-22 17:40:46 來(lái)源:億速云 閱讀:351 作者:小豬 欄目:移動(dòng)開(kāi)發(fā)

小編這次要給大家分享的是Android如何使用RecycleView實(shí)現(xiàn)拖拽交換item位置,文章內(nèi)容豐富,感興趣的小伙伴可以來(lái)了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。

老規(guī)矩,先來(lái)一張效果圖:

Android如何使用RecycleView實(shí)現(xiàn)拖拽交換item位置

相比起ListView而言,RecycleView實(shí)現(xiàn)拖拽交換位置的效果要簡(jiǎn)單很多,因?yàn)橥ㄟ^(guò)SDK中的ItemTouchHelper工具類(lèi)可以輕松的實(shí)現(xiàn)這種效果,并且一套代碼支持所有布局方式;而ListView的話(huà)則需要通過(guò)生成View的緩存鏡像設(shè)置到ImageView中,然后通過(guò)WindowManager來(lái)操作該ImageView,具體怎么實(shí)現(xiàn)這里就不展開(kāi)講解了.回歸到ItemTouchHelper話(huà)題上,這個(gè)工具類(lèi)我們需要關(guān)心的方法只有一個(gè),即:

public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {}

通過(guò)名字也可以知道其作用就是和RecyclerView 建立關(guān)系.
而我們真正需要關(guān)心的地方就是ItemTouchHelper的內(nèi)部類(lèi)ItemTouchHelper.Callback,它是一個(gè)抽象類(lèi),需要我們?nèi)?shí)現(xiàn)下面這幾個(gè)關(guān)鍵的抽象方法以及重寫(xiě)幾個(gè)非抽象的方法:

//決定拖拽/滑動(dòng)的方向
public abstract int getMovementFlags(RecyclerView recyclerView,
    ViewHolder viewHolder);

//和位置交換有關(guān),可用于實(shí)現(xiàn)drag功能
public abstract boolean onMove(RecyclerView recyclerView,
    ViewHolder viewHolder, ViewHolder target);

//和滑動(dòng)有關(guān),可用于實(shí)現(xiàn)swipe功能
public abstract void onSwiped(ViewHolder viewHolder, int direction);

//是否長(zhǎng)按啟用拖拽功能,默認(rèn)是true
public boolean isLongPressDragEnabled() {return true;}

//是否支持滑動(dòng),默認(rèn)true
public boolean isItemViewSwipeEnabled() {return true;}

//和目標(biāo)View的狀態(tài)改變有關(guān),例如drag,swipe,ide
public void onSelectedChanged(ViewHolder viewHolder, int actionState) {}

//和移除View的狀態(tài)有關(guān),通常用于清除在onSelectedChanged,onChildDraw中對(duì)View設(shè)置的動(dòng)畫(huà)
public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {}

當(dāng)創(chuàng)建完ItemTouchHelper.Callback的實(shí)現(xiàn)類(lèi),我這里稱(chēng)之為SimpleItemTouchHelperCallback后,還需要將數(shù)據(jù)的變化以及View的狀態(tài)通知到RecycleView的Adapter中,為了達(dá)到解耦的目的,通??梢酝ㄟ^(guò)定義接口來(lái)實(shí)現(xiàn),在SimpleItemTouchHelperCallback的構(gòu)造方法中傳入該解耦接口的引用,并讓RecycleView的Adapter實(shí)現(xiàn)該解耦的接口,這樣就實(shí)現(xiàn)了這2個(gè)類(lèi)的通信問(wèn)題了.

來(lái)看看我定義的解耦接口:

/**
 * 定義RecycleView的Adapter和SimpleItemTouchHelperCallback直接交互的接口方法
 * Created by mChenys on 2017/2/16.
 */
public interface ItemTouchHelperAdapter {

 //數(shù)據(jù)交換
 void onItemMove(RecyclerView.ViewHolder source, RecyclerView.ViewHolder target);

 //數(shù)據(jù)刪除
 void onItemDissmiss(RecyclerView.ViewHolder source);

 //drag或者swipe選中
 void onItemSelect(RecyclerView.ViewHolder source);

 //狀態(tài)清除
 void onItemClear(RecyclerView.ViewHolder source);
}

完整的SimpleItemTouchHelperCallback代碼如下:

/**
 * 處理RecycleView的選中,拖拽移動(dòng),拖拽刪除的實(shí)現(xiàn)類(lèi)
 * Created by mChenys on 2017/2/16.
 */
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

 private ItemTouchHelperAdapter mAdapter;

 public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
  mAdapter = adapter;
 }

 @Override
 public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
  //int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允許上下的拖動(dòng)
  //int dragFlags =ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允許左右的拖動(dòng)
  //int swipeFlags = ItemTouchHelper.LEFT; //只允許從右向左側(cè)滑
  //int swipeFlags = ItemTouchHelper.DOWN; //只允許從上向下側(cè)滑
  //一般使用makeMovementFlags(int,int)或makeFlag(int, int)來(lái)構(gòu)造我們的返回值
  //makeMovementFlags(dragFlags, swipeFlags)

  int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允許上下左右的拖動(dòng)
  return makeMovementFlags(dragFlags, 0);
 }

 @Override
 public boolean isLongPressDragEnabled() {
  return true;//長(zhǎng)按啟用拖拽
 }

 @Override
 public boolean isItemViewSwipeEnabled() {
  return false; //不啟用拖拽刪除
 }

 @Override
 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
  //通過(guò)接口傳遞拖拽交換數(shù)據(jù)的起始位置和目標(biāo)位置的ViewHolder
  mAdapter.onItemMove(source, target);
  return true;
 }


 @Override
 public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
  //移動(dòng)刪除回調(diào),如果不用可以不用理
  // mAdapter.onItemDissmiss(viewHolder);
 }

 @Override
 public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
  super.onSelectedChanged(viewHolder, actionState);
  if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
   //當(dāng)滑動(dòng)或者拖拽view的時(shí)候通過(guò)接口返回該ViewHolder
   mAdapter.onItemSelect(viewHolder);
  }
 }

 @Override
 public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
  super.clearView(recyclerView, viewHolder);
  if (!recyclerView.isComputingLayout()) {
   //當(dāng)需要清除之前在onSelectedChanged或者onChildDraw,onChildDrawOver設(shè)置的狀態(tài)或者動(dòng)畫(huà)時(shí)通過(guò)接口返回該ViewHolder
   mAdapter.onItemClear(viewHolder);
  }
 }
}

RecycleView.Adapter實(shí)現(xiàn)類(lèi)代碼

/**
 * Created by mChenys on 2017/2/15.
 */
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements ItemTouchHelperAdapter {
 ...

 @Override
 public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  ...
 }

 @Override
 public void onBindViewHolder(final MyAdapter.MyViewHolder holder, int position) {
  ...
 }

 @Override
 public int getItemCount() {
  //注意:這里最少有一個(gè),因?yàn)橛卸嗔艘粋€(gè)添加按鈕
  return null == mData &#63; 1 : mData.size() + 1;
 }

 @Override
 public void onItemMove(RecyclerView.ViewHolder source,
  RecyclerView.ViewHolder target) {
  int fromPosition = source.getAdapterPosition();
  int toPosition = target.getAdapterPosition();
  if (fromPosition < mData.size() && toPosition < mData.size()) {
   //交換數(shù)據(jù)位置
   Collections.swap(mData, fromPosition, toPosition);
   //刷新位置交換
   notifyItemMoved(fromPosition, toPosition);
  }
  //移動(dòng)過(guò)程中移除view的放大效果
  onItemClear(source);
 }

 @Override
 public void onItemDissmiss(RecyclerView.ViewHolder source) {

  int position = source.getAdapterPosition();
  mData.remove(position); //移除數(shù)據(jù)
  notifyItemRemoved(position);//刷新數(shù)據(jù)移除
 }

 @Override
 public void onItemSelect(RecyclerView.ViewHolder viewHolder) {

  //當(dāng)拖拽選中時(shí)放大選中的view
  viewHolder.itemView.setScaleX(1.2f);
  viewHolder.itemView.setScaleY(1.2f);
 }

 @Override
 public void onItemClear(RecyclerView.ViewHolder viewHolder) {

  //拖拽結(jié)束后恢復(fù)view的狀態(tài)
  viewHolder.itemView.setScaleX(1.0f);
  viewHolder.itemView.setScaleY(1.0f);
 }

 public class MyViewHolder extends RecyclerView.ViewHolder {
  ...

  public MyViewHolder(View itemView) {
   super(itemView);
   ...
  }
 }

}

MainActivity的使用方式

/**
 * Created by mChenys on 2017/2/16.
 */
public class MainActivity extends AppCompatActivity {
 ...
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ...
  mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
  //創(chuàng)建adapter
  MyAdapter myAdapter = new MyAdapter(this, mData);
  //設(shè)置默認(rèn)的布局方式
  mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
  //設(shè)置adapter
  mRecyclerView.setAdapter(myAdapter);
  //創(chuàng)建SimpleItemTouchHelperCallback
  ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(myAdapter);
  //用Callback構(gòu)造ItemtouchHelper
  ItemTouchHelper touchHelper = new ItemTouchHelper(callback); 
  //調(diào)用ItemTouchHelper的attachToRecyclerView方法建立聯(lián)系
  touchHelper.attachToRecyclerView(mRecyclerView);
 }



 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  ...
  return super.onCreateOptionsMenu(menu);
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  ...
  return super.onOptionsItemSelected(item);
 }

}

看完這篇關(guān)于Android如何使用RecycleView實(shí)現(xiàn)拖拽交換item位置的文章,如果覺(jué)得文章內(nèi)容寫(xiě)得不錯(cuò)的話(huà),可以把它分享出去給更多人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI