Ich bin kürzlich auf diesen großartigen Kern gestoßen , der eine funktionierende Implementierung einer Drag-Sortierung ListView
bietet, ohne dass externe Abhängigkeiten erforderlich sind.
Grundsätzlich besteht es darin, einen benutzerdefinierten Adapter zu erstellen, der sich ArrayAdapter
als innere Klasse auf die Aktivität erstreckt, die Ihren enthält ListView
. Auf diesem Adapter setzt man dann einen onTouchListener
auf Ihre Listenelemente, der den Beginn des Ziehens signalisiert.
In diesem Gist setzen sie den Listener auf einen bestimmten Teil des Layouts des Listenelements (das "Handle" des Elements), sodass man es nicht versehentlich bewegt, indem man einen Teil davon drückt. Persönlich habe ich es vorgezogen, stattdessen mit einem zu gehen onLongClickListener
, aber es liegt an Ihnen, zu entscheiden. Hier ein Auszug aus diesem Teil:
public class MyArrayAdapter extends ArrayAdapter<String> {
private ArrayList<String> mStrings = new ArrayList<String>();
private LayoutInflater mInflater;
private int mLayout;
//constructor, clear, remove, add, insert...
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
//inflate, etc...
final String string = mStrings.get(position);
holder.title.setText(string);
// Here the listener is set specifically to the handle of the layout
holder.handle.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
startDrag(string);
return true;
}
return false;
}
});
// change color on dragging item and other things...
return view;
}
}
Dazu gehört auch das Hinzufügen eines onTouchListener
zu ListView
, das prüft, ob ein Element gezogen wird, das Austauschen und die Ungültigmachung behandelt und den Ziehstatus stoppt. Ein Auszug aus diesem Teil:
mListView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent event) {
if (!mSortable) { return false; }
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
// get positions
int position = mListView.pointToPosition((int) event.getX(),
(int) event.getY());
if (position < 0) {
break;
}
// check if it's time to swap
if (position != mPosition) {
mPosition = position;
mAdapter.remove(mDragString);
mAdapter.insert(mDragString, mPosition);
}
return true;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE: {
//stop drag state
stopDrag();
return true;
}
}
return false;
}
});
Abschließend sehen Sie, wie die Methoden stopDrag
und startDrag
aussehen, die das Aktivieren und Deaktivieren des Ziehvorgangs behandeln:
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}