在 Android 上,我使用 aListView
并且我希望能够使用拖放重新排序其项目。我知道“拖放列表视图”有不同的实现,但是我想使用自API 级别 11以来的拖放框架。
它开始得很好,直到我想ListView
在拖放时滚动。正如在下面的示例中所写,现在,我检查我在哪个列表元素的顶部,所以如果它的位置不在中间ListView.getLastVisiblePosition()
,ListView.getFirstVisiblePosition()
我使用 aListView.smoothScrollToPosition()
查看其他列表项。
这是第一个实现,但效果很好。
DragEvent.ACTION_DRAG_ENTERED
滚动时出现问题:当我在它们之上时,一些元素不响应拖放事件 -以及其他事件。这是由于 ListView 管理其项目视图的方式:它试图回收不再可见的项目视图。
没关系,它可以工作,但有时getView()
返回ListAdapter
一个新对象。因为它是新的,所以这个对象错过了,DragEvent.ACTION_DRAG_STARTED
所以它不响应其他DragEvent
事件!
这是一个例子。在这种情况下,如果我通过长按列表项开始拖放,如果我拖动它,如果我在它们上面,大多数项目将具有绿色背景;但有些没有。
即使他们错过了让他们订阅拖放事件机制的任何想法DragEvent.ACTION_DRAG_STARTED
?
// Somewhere I have a ListView that use the MyViewAdapter
// MyListView _myListView = ...
// _myListView.setAdapter(new MyViewAdapter(getActivity(), ...));
_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;
}
});
class MyViewAdapter extends ArrayAdapter<MyElement> {
public MyViewAdapter(Context context, List<TimedElement> objects) {
super(context, 0, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View myElementView = convertView;
if (myElementView == null) {
/* If the code is executed here while scrolling with a drag and drop,
* the new view is not associated to the current drag and drop events */
Log.d("app", "Object created!");
// Create view
// myElementView = ...
// Prepare drag and drop
myElementView.setOnDragListener(new MyElementDragListener());
}
// Associates view and position in ListAdapter, needed for drag and drop
myElementView.setTag(R.id.item_position, position);
// Continue to prepare view
// ...
return timedElementView;
}
private class MyElementDragListener 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_ENTERED:
v.setBackgroundColor(Color.GREEN);
v.invalidate();
return true;
case DragEvent.ACTION_DRAG_LOCATION:
int targetPosition = (Integer)v.getTag(R.id.item_position);
if (event.getY() < v.getHeight()/2 ) {
Log.i("app", "top "+targetPosition);
}
else {
Log.i("app", "bottom "+targetPosition);
}
// To scroll in ListView while doing drag and drop
if (targetPosition > _myListView.getLastVisiblePosition()-2) {
_myListView.smoothScrollToPosition(targetPosition+2);
}
else if (targetPosition < _myListView.getFirstVisiblePosition()+2) {
_myListView.smoothScrollToPosition(targetPosition-2);
}
return true;
case DragEvent.ACTION_DRAG_EXITED:
v.setBackgroundColor(Color.BLUE);
v.invalidate();
return true;
case DragEvent.ACTION_DROP:
case DragEvent.ACTION_DRAG_ENDED:
default:
break;
}
return false;
}
}
}