參考資料
背景介紹
列表控件可以說是我們絕大部分App中都會(huì)使用的往堡,為了提升交互樂趣,我們經(jīng)常需要在列表中加入拖拽共耍、滑動(dòng)等操作,本篇我將介紹使用ItemDragHelper這個(gè)官方提供的交互幫助類來幫助RecyclerView實(shí)現(xiàn)這些復(fù)雜的交互吨瞎。
走進(jìn)ItemTouchHelper
要使用這個(gè)類痹兜,最關(guān)鍵的步驟是傳給它一個(gè)ItemTouchHelper.Callback,其它的我們可以不用管颤诀。既然它是一個(gè)Callback字旭,那么我們可以大概猜到,我們自然就是在它的一些回調(diào)函數(shù)里做操作了崖叫。下面我們就來看看我們需要在哪些回調(diào)函數(shù)里做操作遗淳。
先上個(gè)效果圖:
public class CustomItemTouchHelperCallback extends ItemTouchHelper.Callback {
private OnItemTouchCallbackListener onItemTouchCallbackListener;
private boolean canDrag = true;
private boolean canSwipe = true;
public CustomItemTouchHelperCallback(OnItemTouchCallbackListener onItemTouchCallbackListener) {
this.onItemTouchCallbackListener = onItemTouchCallbackListener;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
int dragFlags = 0;
int swipeFlags = 0;
if (layoutManager instanceof GridLayoutManager) {
// 如果是Grid布局,則不能滑動(dòng)心傀,只能上下左右拖動(dòng)
dragFlags =
ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
swipeFlags = 0;
} else if (layoutManager instanceof LinearLayoutManager) {
// 如果是縱向Linear布局屈暗,則能上下拖動(dòng),左右滑動(dòng)
if (((LinearLayoutManager) layoutManager).getOrientation() == LinearLayoutManager.VERTICAL) {
dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
swipeFlags = ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
} else {
// 如果是橫向Linear布局脂男,則能左右拖動(dòng),上下滑動(dòng)
swipeFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
dragFlags = ItemTouchHelper.LEFT|ItemTouchHelper.RIGHT;
}
}
return makeMovementFlags(dragFlags, swipeFlags); //該方法指定可進(jìn)行的操作
}
/**
* 拖動(dòng)時(shí)回調(diào),在這里處理拖動(dòng)事件
*
* @param viewHolder 被拖動(dòng)的view
* @param target 目標(biāo)位置的view
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
//這里我們直接將參數(shù)傳遞到回調(diào)接口方法中可缚,提高復(fù)用性
return onItemTouchCallbackListener.onMove(recyclerView, viewHolder, target);
}
/**
* 滑動(dòng)時(shí)回調(diào)
*
* @param direction 回調(diào)方向
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
onItemTouchCallbackListener.onSwiped(viewHolder, direction);
}
/**
* 在這個(gè)回調(diào)中颤难,如果返回true,表示可以觸發(fā)長按拖動(dòng)事件汁讼,false則表示不能
*/
@Override
public boolean isLongPressDragEnabled() {
return canDrag;
}
/**
* 在這個(gè)回調(diào)中淆攻,如果返回true,表示可以觸發(fā)滑動(dòng)事件嘿架,false表示不能
*/
@Override
public boolean isItemViewSwipeEnabled() {
return canSwipe;
}
public void setCanDrag(boolean canDrag) {
this.canDrag = canDrag;
}
public void setCanSwipe(boolean canSwipe) {
this.canSwipe = canSwipe;
}
}
下面我們看看怎么來使用這個(gè)我們自定義的Callback瓶珊。
public class DraggerRecyclerViewActivity extends BaseActivity {
@BindView(R.id.rv_dragger_list)
RecyclerView draggerList;
private List<String> datas = new ArrayList<>();
private TextTestAdapter adapter;
private CustomItemTouchHelper itemTouchHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dragger_recycler_view);
ButterKnife.bind(this);
initData();
initView();
addListener();
}
@Override
protected void initData() {
for (int i = 0; i < 100; i++) {
datas.add("我是Item" + i);
}
}
@Override
protected void initView() {
draggerList.setItemAnimator(new DefaultItemAnimator());
draggerList.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (itemPosition != parent.getChildCount() - 1) {
outRect.bottom = (int) DisplayUtils.dipToPx(0.5f);
}
}
});
draggerList.setLayoutManager(new LinearLayoutManager(this));
adapter = new TextTestAdapter(this, datas);
//創(chuàng)建ItemTouchHelper
itemTouchHelper = new CustomItemTouchHelper(new OnItemTouchCallbackListener() {
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
if (datas == null) {
return false;
}
//處理拖動(dòng)排序
//使用Collection對(duì)數(shù)組進(jìn)行重排序,目的是把我們拖動(dòng)的Item換到下一個(gè)目標(biāo)Item的位置
Collections.swap(datas, viewHolder.getAdapterPosition(), target.getAdapterPosition());
//通知Adapter它的Item發(fā)生了移動(dòng)
adapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
if (datas == null) {
return;
}
//處理滑動(dòng)刪除
//直接從數(shù)據(jù)中刪除該Item的數(shù)據(jù)
datas.remove(viewHolder.getAdapterPosition());
//通知Adapter有Item被移除了
adapter.notifyItemRemoved(viewHolder.getAdapterPosition());
}
});
//并綁定RecyclerView
itemTouchHelper.attachToRecyclerView(draggerList);
draggerList.setAdapter(adapter);
}
@Override
protected void addListener() {
}
}
下面是ItemTouchHelper眶明。
public class CustomItemTouchHelper extends ItemTouchHelper {
public CustomItemTouchHelper(OnItemTouchCallbackListener onItemTouchCallbackListener) {
//直接把回調(diào)交給父類處理就好
super(new CustomItemTouchHelperCallback(onItemTouchCallbackListener));
}
}
很簡單是不是艰毒?把它自定義出來其實(shí)就是為了防止后期還要添加別的操作,如果不需要搜囱,可以直接用API中的ItemTouchHelper丑瞧。
總結(jié)
歸根結(jié)底柑土,使用ItemTouchHelper來實(shí)現(xiàn)RecyclerView的拖拽、滑動(dòng)操作绊汹,最主要的還是重寫ItemTouchHelper.Callback稽屏,在這個(gè)回調(diào)中,比較重要的方法是以下幾個(gè):
- getMovementFlags(): 這個(gè)方法中需要返回可進(jìn)行的操作Flags西乖,這些Flags需要調(diào)用下面的方法合成狐榔;
- makeMovementFlags():這個(gè)方法將drag和move操作的Flags合成,作為getMovementFlags中的返回項(xiàng)获雕;
- onMove():發(fā)生拖動(dòng)時(shí)調(diào)用薄腻;
- onSwiped():發(fā)生滑動(dòng)時(shí)調(diào)用;
- isLongPressDragEnabled():是否能觸發(fā)長按拖動(dòng)届案;
- isItemViewSwipeEnabled():是否能觸發(fā)滑動(dòng)庵楷;
探討
最近看到一個(gè)觀點(diǎn),說美國犯罪率的下降應(yīng)該大部分歸功于墮胎合法化的政策楣颠,而不是別的因素尽纽。因?yàn)閴櫶ナ购芏嗟讓尤嗣瘢麄円馔鈶言型觯瑓s無力好好撫養(yǎng)孩子弄贿,提供良好的生存環(huán)境給他們,這些孩子在未來是最有可能從事犯罪的矫膨。而墮胎的合法化使這些孩子一部分未能來到這個(gè)世界上差凹,所以從根源上導(dǎo)致了犯罪率的下降。
這事兒豆拨,你怎么看直奋?
如果這篇文章對(duì)你有幫助的話,記得點(diǎn)個(gè)贊施禾,關(guān)注走一波哦脚线!