Su Android, utilizzo uno ListView
e voglio essere in grado di riordinarne gli elementi usando il drag and drop. So che ci sono diverse implementazioni di una "lista di selezione drag and drop", tuttavia voglio utilizzare lo Drag and Drop framework in arrivo dal livello di API .Drag and drop, ListView e item Views che perdono l'evento ACTION_DRAG_STARTED
E 'iniziato molto bene fino a quando ho voluto scorrere il mio ListView
mentre si fa un drag and drop. Come è scritto nell'esempio seguente, per ora, controllo in cima a quale elemento di lista sono, quindi se la sua posizione non è compresa tra ListView.getLastVisiblePosition()
e ListView.getFirstVisiblePosition()
, utilizzo uno ListView.smoothScrollToPosition()
per visualizzare gli altri elementi dell'elenco.
È una prima implementazione ma funziona piuttosto bene.
Il problema si verifica durante lo scorrimento: alcuni elementi non rispondono agli eventi di trascinamento della selezione - DragEvent.ACTION_DRAG_ENTERED
e gli altri - quando sono sopra di essi. È dovuto al modo in cui ListView gestisce le sue visualizzazioni di articoli: tenta di riciclare le viste degli articoli che non sono più visibili.
Va tutto bene e funziona, ma a volte il getView()
di ListAdapter
restituisce un nuovo oggetto. Dal momento che è nuovo, questo oggetto ha perso il DragEvent.ACTION_DRAG_STARTED
in modo che non risponda agli altri eventi DragEvent
!
Ecco un esempio. In questo caso, se avvio un trascinamento con un clic lungo su un elemento dell'elenco e se lo trascino, la maggior parte degli elementi avrà uno sfondo verde se sono sopra di essi; ma alcuni no.
Qualche idea su come farli iscrivere al meccanismo di trascinamento degli eventi, anche se hanno perso il 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;
}
}
}
non ho provato questo, ma chi sa forse un giorno lo farò. Questo sembra un buon lavoro, e abbastanza tecnico! Voto positivo da parte mia –