我有same problem。我没有解决这个回收问题,但我发现了一个可能的解决方法,仍然使用拖放框架。这个想法是改变视角:而不是在列表中的每个View上使用OnDragListener,它可以直接在ListView上使用。
然后想法是在进行拖放时找到手指在哪个项目上,并在ListView的ListAdapter中编写相关的显示代码。然后,诀窍是找到我们在哪个项目视图之上,以及放置完成的位置。
为了做到这一点,我将适配器创建的每个视图的ListView 位置设置为id - 使用View.setId(),这样我以后可以使用ListView.pointToPosition() 和@987654331 的组合找到它@。
作为一个拖动监听器示例(我提醒你,它应用于ListView),它可以是这样的:
// Initalize your ListView
private ListView _myListView = new ListView(getContext());
// Start drag when long click on a ListView item
_myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(null, shadowBuilder, _myListView.getItemAtPosition(position), 0);
return true;
}
});
// Set the adapter and drag listener
_myListView.setOnDragListener(new MyListViewDragListener());
_myListView.setAdapter(new MyViewAdapter(getActivity()));
// Classes used above
private class MyViewAdapter extends ArrayAdapter<Object> {
public MyViewAdapter (Context context, List<TimedElement> objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View myView = convertView;
if (myView == null) {
// Instanciate your view
}
// Associates view and position in ListAdapter, needed for drag and drop
myView.setId(position);
return myView;
}
}
private class MyListViewDragListener implements View.OnDragListener {
@Override
public boolean onDrag(View v, DragEvent event) {
final int action = event.getAction();
switch(action) {
case DragEvent.ACTION_DRAG_STARTED:
return true;
case DragEvent.ACTION_DRAG_DROP:
// We drag the item on top of the one which is at itemPosition
int itemPosition = _myListView.pointToPosition((int)event.getX(), (int)event.getY());
// We can even get the view at itemPosition thanks to get/setid
View itemView = _myListView.findViewById(itemPosition );
/* If you try the same thing in ACTION_DRAG_LOCATION, itemView
* is sometimes null; if you need this view, just return if null.
* As the same event is then fired later, only process the event
* when itemView is not null.
* It can be more problematic in ACTION_DRAG_DROP but for now
* I never had itemView null in this event. */
// Handle the drop as you like
return true;
}
}
}
现在,如果您在进行拖放操作时需要视觉反馈,有几种策略。例如,您的活动中可以有 2 个实例变量,名为:
private boolean ongoingDrag = false; // To know if we are in a drag&drop state
private int dragPosition = 0; // You put the itemPosition variable here
在MyListViewDragListener 中进行拖放时,您会修改这些变量,并在MyViewAdapter 中使用它们的状态。当然不要忘记使用 _myListView.getAdapter()).notifyDataSetChanged() 或 _myListView.invalidate() 之类的方法更新 UI(当然,在事件线程中使用 Handler)。