Android使用RecycleView實(shí)現(xiàn)拖拽交換item位置
本文實(shí)例為大家分享了RecycleView實(shí)現(xiàn)拖拽交換item位置的具體代碼,供大家參考,具體內(nèi)容如下
老規(guī)矩,先來(lái)一張效果圖:
相比起ListView而言,RecycleView實(shí)現(xiàn)拖拽交換位置的效果要簡(jiǎn)單很多,因?yàn)橥ㄟ^(guò)SDK中的ItemTouchHelper工具類(lèi)可以輕松的實(shí)現(xiàn)這種效果,并且一套代碼支持所有布局方式;而ListView的話則需要通過(guò)生成View的緩存鏡像設(shè)置到ImageView中,然后通過(guò)WindowManager來(lái)操作該ImageView,具體怎么實(shí)現(xiàn)這里就不展開(kāi)講解了.回歸到ItemTouchHelper話題上,這個(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),我這里稱之為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 ? 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); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Win10下android studio開(kāi)發(fā)環(huán)境配置圖文教程
這篇文章主要為大家詳細(xì)介紹了Win10下android studio開(kāi)發(fā)環(huán)境配置圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07android studio 新建項(xiàng)目報(bào)錯(cuò)的解決之路
這篇文章主要介紹了android studio 新建工程報(bào)錯(cuò),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Flutter改變狀態(tài)變量是否必須寫(xiě)在setState回調(diào)詳解
這篇文章主要為大家介紹了Flutter改變狀態(tài)變量是否必須寫(xiě)在setState回調(diào)里的原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Android通過(guò)HTTP協(xié)議實(shí)現(xiàn)上傳文件數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Android通過(guò)HTTP協(xié)議實(shí)現(xiàn)上傳文件數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android自定義Drawable之在Drawable中部指定透明區(qū)域方法示例
對(duì)于不同的屏幕密度、不同的設(shè)備方向,不同的語(yǔ)言和區(qū)域,都會(huì)涉及到備選 drawable 資源,下面這篇文章主要給你大家介紹了關(guān)于Android自定義Drawable之在Drawable中部指定透明區(qū)域的相關(guān)資料,需要的朋友可以參考下2018-07-07Android Drawerlayout實(shí)現(xiàn)側(cè)滑菜單效果
這篇文章主要為大家詳細(xì)介紹了Android Drawerlayout實(shí)現(xiàn)側(cè)滑菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android觸摸事件如何實(shí)現(xiàn)筆觸畫(huà)布詳解
這篇文章主要給大家介紹了關(guān)于Android觸摸事件如何實(shí)現(xiàn)筆觸畫(huà)布的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-10-10Android實(shí)現(xiàn)類(lèi)似IOS右滑返回的效果(原因分析及解決辦法)
這篇文章主要介紹了Android實(shí)現(xiàn)類(lèi)似IOS右滑返回的效果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下2017-03-03Android開(kāi)發(fā)之進(jìn)度條ProgressBar的示例代碼
本篇文章主要介紹了Android開(kāi)發(fā)之進(jìn)度條ProgressBar的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03分享10個(gè)很棒的學(xué)習(xí)Android開(kāi)發(fā)的網(wǎng)站
我推薦的網(wǎng)站,都是我在學(xué)習(xí)Android 開(kāi)發(fā)過(guò)程中發(fā)現(xiàn)的好網(wǎng)站,給初學(xué)者一些建議,少走一些彎路2015-03-03