Niedawno natknąłem się na ten wspaniały Gist, który daje działającą implementację typu przeciągania ListView, bez konieczności stosowania zewnętrznych zależności.
Zasadniczo polega na utworzeniu własnego adaptera rozszerzającego się ArrayAdapterjako klasa wewnętrzna do działania zawierającego ListView. Na tym adapterze ustawia się następnie onTouchListenerna elementy listy, które będą sygnalizować początek przeciągania.
W tym streszczeniu ustawiają słuchacza na określoną część układu elementu listy („uchwyt” elementu), więc nie można przypadkowo przesunąć go przez naciśnięcie jakiejkolwiek jego części. Osobiście wolałem onLongClickListenerzamiast tego, ale decyzja należy do ciebie. Oto fragment tej części:
public class MyArrayAdapter extends ArrayAdapter<String> {
private ArrayList<String> mStrings = new ArrayList<String>();
private LayoutInflater mInflater;
private int mLayout;
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View view = convertView;
final String string = mStrings.get(position);
holder.title.setText(string);
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;
}
});
return view;
}
}
Obejmuje to również dodanie onTouchListenerdo ListView, które sprawdza, czy element jest przeciągany, obsługuje zamianę i unieważnianie oraz zatrzymuje stan przeciągania. Fragment tej części:
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: {
int position = mListView.pointToPosition((int) event.getX(),
(int) event.getY());
if (position < 0) {
break;
}
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: {
stopDrag();
return true;
}
}
return false;
}
});
Wreszcie, oto jak wyglądają metody stopDragi startDrag, które obsługują włączanie i wyłączanie procesu przeciągania:
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}