Android使用RecycleView實(shí)現(xiàn)拖拽交換item位置
本文實(shí)例為大家分享了RecycleView實(shí)現(xiàn)拖拽交換item位置的具體代碼,供大家參考,具體內(nèi)容如下
老規(guī)矩,先來一張效果圖:

相比起ListView而言,RecycleView實(shí)現(xiàn)拖拽交換位置的效果要簡單很多,因?yàn)橥ㄟ^SDK中的ItemTouchHelper工具類可以輕松的實(shí)現(xiàn)這種效果,并且一套代碼支持所有布局方式;而ListView的話則需要通過生成View的緩存鏡像設(shè)置到ImageView中,然后通過WindowManager來操作該ImageView,具體怎么實(shí)現(xiàn)這里就不展開講解了.回歸到ItemTouchHelper話題上,這個(gè)工具類我們需要關(guān)心的方法只有一個(gè),即:
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {}
通過名字也可以知道其作用就是和RecyclerView 建立關(guān)系.
而我們真正需要關(guān)心的地方就是ItemTouchHelper的內(nèi)部類ItemTouchHelper.Callback,它是一個(gè)抽象類,需要我們?nèi)?shí)現(xiàn)下面這幾個(gè)關(guān)鍵的抽象方法以及重寫幾個(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);
//是否長按啟用拖拽功能,默認(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中對View設(shè)置的動(dòng)畫
public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {}
當(dāng)創(chuàng)建完ItemTouchHelper.Callback的實(shí)現(xiàn)類,我這里稱之為SimpleItemTouchHelperCallback后,還需要將數(shù)據(jù)的變化以及View的狀態(tài)通知到RecycleView的Adapter中,為了達(dá)到解耦的目的,通常可以通過定義接口來實(shí)現(xiàn),在SimpleItemTouchHelperCallback的構(gòu)造方法中傳入該解耦接口的引用,并讓RecycleView的Adapter實(shí)現(xiàn)該解耦的接口,這樣就實(shí)現(xiàn)了這2個(gè)類的通信問題了.
來看看我定義的解耦接口:
/**
* 定義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)類
* 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)來構(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;//長按啟用拖拽
}
@Override
public boolean isItemViewSwipeEnabled() {
return false; //不啟用拖拽刪除
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
//通過接口傳遞拖拽交換數(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í)候通過接口返回該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)畫時(shí)通過接口返回該ViewHolder
mAdapter.onItemClear(viewHolder);
}
}
}
RecycleView.Adapter實(shí)現(xiàn)類代碼
/**
* 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)過程中移除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);
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android 嵌套Fragment的使用實(shí)例代碼
本文主要介紹Android Fragment,在這里提供了實(shí)例代碼跟效果圖,希望能幫助有需要的小伙伴2016-07-07
Android Service自啟動(dòng)注意事項(xiàng)分析
這篇文章主要介紹了Android Service自啟動(dòng)注意事項(xiàng),結(jié)合實(shí)例分析了Android Service自啟動(dòng)過程中屬性設(shè)置的相關(guān)技巧,需要的朋友可以參考下2016-03-03
Android 在 res/layout 文件夾 下創(chuàng)建一個(gè) 子文件夾實(shí)例
這篇文章主要介紹了Android 在 res/layout 文件夾 下創(chuàng)建一個(gè) 子文件夾實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
創(chuàng)建子線程對Android進(jìn)行網(wǎng)絡(luò)訪問
這篇文章介紹了Android中創(chuàng)建子線程進(jìn)行網(wǎng)絡(luò)訪問的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考2021-11-11
Android中ListView的item點(diǎn)擊沒有反應(yīng)的解決方法
這篇文章主要介紹了Android中ListView的item點(diǎn)擊沒有反應(yīng)的相關(guān)資料,需要的朋友可以參考下2017-10-10
android studio實(shí)現(xiàn)簡單的計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了android studio實(shí)現(xiàn)簡單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05

