我正在尝试开发一个简单但自定义的recyclelerview项目的拖放功能。这个想法是将一个孩子拖到一个特定的视图,由一个FrameLayout表示,该视图不是recyclerview的子代。 当孩子被摔到它上面时,它将被删除,否则它将简单地返回其原始位置。 我可以很容易地实现这种行为而没有任何动画效果,但我的目的是在UP dragevent和元素的恢复上有平滑的动画。现在每当拖动一个子项时,我都会创建一个DragShadow,然后删除数据集中的子项并使用adapter.notifyItemRemoved(position)通知删除。 最后一个允许我使用Recyclerview本身提供的简单删除动画。 守则将比言辞更好地解释机制:
public boolean dragNdrop(View arg1, int position) {
// ------------------------
final RecyclerAdapter adapter= ListItemFragment.getAdapter();
/*Keep track of the position and the object for restoring purpose*/
ListItemFragment.indexAbruptedRemoved=position;
ListItemFragment.itemAbruptedRemoved=adapter.getItem(position);
ClipData clipData = ClipData.newPlainText("", "");
View.DragShadowBuilder dsb = new View.DragShadowBuilder(arg1);
arg1.startDrag(clipData, dsb, arg1, 0);
adapter.remove(position);
adapter.notifyItemRemoved(position);
//--------------------
}
适配器的getter方法:
protected static RecyclerAdapter getAdapter() {
return (RecyclerAdapter) recList.getAdapter();
}
dragNdrop由自定义适配器中的拖动侦听器调用:
public void onBindViewHolder(MyHolder myHolder, int position) {
//----------------------------------
myHolder.rowCard.setLongClickable(true);
myHolder.rowCard.setOnClickListener(new MyClickListener.ContainerListener(context,
myHolder.getAdapterPosition(), rowObject, myHolder.imagePreView));
myHolder.rowCard.setOnLongClickListener(new MyClickListener.DragListener(context,
myHolder.getAdapterPosition(), myHolder.rowCard));
//----------------------------------
}
LongCLickListener:
static class DragListener implements View.OnLongClickListener {
private Context context;
private int position;
private View dragged;
DragListener(Context context, int position, View dragged) {
this.context = context;
this.position = position;
this.dragged = dragged;
}
@Override
public boolean onLongClick(View v) {
return ((MainActivity) context).dragNdrop(dragged, position);
}
}
名为trashPanel的FrameLayout具有以下代码:
trashPanel.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View view, DragEvent dragEvent) {
int dragAction = dragEvent.getAction();
View dragView = (View) dragEvent.getLocalState();//this
//is properly the object we 've passed with startdrag()
switch (dragAction) {
case DragEvent.ACTION_DRAG_EXITED:
imageView.setImageDrawable(getResources().getDrawable(R.drawable.bowl));
break;
case DragEvent.ACTION_DRAG_ENTERED:
imageView.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.waste));
break;
case DragEvent.ACTION_DRAG_ENDED:
ended(view, dragEvent);
break;
case DragEvent.ACTION_DROP:
Log.i(TAG,"HALOOOOO DROPPED");
drop();
break;
}
return true;
}//[m] end on drag
private void drop() {
String itemToRemove = itemAbruptedRemoved.getSessionName();
Toast.makeText(getActivity(), "DELETED: " + itemToRemove+
" list length:"+items.size()+" adapter length:"+mAdapter.size(),
Toast.LENGTH_SHORT).show();
/**
* HAPTIC FEEDBACK
*/
Vibrator v = (Vibrator) getActivity().getSystemService(Service.VIBRATOR_SERVICE);
long pattern[] = {25, 25, 50};
v.vibrate(pattern, -1);// -1 to not repeat
}
private void ended(View view, DragEvent dragEvent) {
if ( dropEventNotHandled(dragEvent) ) {
mAdapter.insert(itemAbruptedRemoved, indexAbruptedRemoved);
mAdapter.notifyItemInserted(indexAbruptedRemoved);
//********---------->mAdapter.notifyDataSetChanged();
Log.i(TAG,"AGGIUNTO");
}
//change the image inside trash_panel
imageView.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.bowl));
//due to implementations detail it must be done in this way(otherwise mutithread exception is throwned)
view.post(new Runnable() {
public void run() {
/**
* Set animation for fabNew Button and trash_panel
* in order to make them smoothly disappear
* and place them in their original positions
*
*/
------------------------------------
}
});
}
private boolean dropEventNotHandled(DragEvent dragEvent) {
return !dragEvent.getResult();
}
});
问题在于,有时当我开始拖动项目时,我会获得正确的DragShadow,但删除的项目是错误的。 在代码我高举*** ---->对notifyDataSetChanged()的调用,因为如果我调用它,一切正常,但没有动画。
我知道有一些实用程序类,如ItemTouchHelper.Callback,应该用来操纵recyclerlist子项的移动和动画,但是我无法弄清楚如何设法让它们做我想做的事情。我看到了一些可用于实现此目的的方法,例如onChildDrawOver和onChildDraw,但我仍然不知道如何使用它们来拦截dragevent.DROP。我也知道LLM的接口名为ItemTouchHelper.ViewDropHandler,它有抽象方法prepareForDrop,但我仍然不知道如何正确使用它。
提前感谢所有帮助我的人!