在Android上,我使用了ListView
,我希望能夠使用拖放操作重新排序項目。我知道有一個「拖放列表視圖」的不同實現,但是我想使用自API級別11以來的Drag and Drop framework。拖放,ListView和缺失ACTION_DRAG_STARTED事件的項目視圖
它開始很好,直到我想滾動我的ListView
而做拖放。正如它在下面的例子中寫的,現在,我檢查我是哪個列表元素的頂部,所以如果它的位置不在ListView.getLastVisiblePosition()
和ListView.getFirstVisiblePosition()
之間,我使用ListView.smoothScrollToPosition()
來查看其他列表項目。
這是第一次實施,但它工作得很好。
滾動時出現問題:某些元素無法應答拖放事件 - DragEvent.ACTION_DRAG_ENTERED
和其他元素 - 當我處於頂部時。這是由於ListView管理其項目視圖的方式:它試圖回收不再可見的項目視圖。
它是好的,它的工作原理,但有時ListAdapter
getView()
返回一個新的對象。由於它是新的,此對象錯過了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;
}
}
}
我沒有嘗試這一點,但誰知道也許有一天我會的。這似乎是一個很好的工作,而且技術性很強! Upvote從我。 –