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ę ArrayAdapter
jako klasa wewnętrzna do działania zawierającego ListView
. Na tym adapterze ustawia się następnie onTouchListener
na 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 onLongClickListener
zamiast 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 onTouchListener
do 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 stopDrag
i 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();
}