Gần đây tôi đã tình cờ thấy Gist tuyệt vời này cung cấp một triển khai hoạt động của một loại kéo ListView
, không cần phụ thuộc bên ngoài.
Về cơ bản, nó bao gồm việc tạo Bộ điều hợp tùy chỉnh của bạn mở rộng ArrayAdapter
như một lớp bên trong cho hoạt động chứa của bạn ListView
. Trên bộ điều hợp này, sau đó đặt một onTouchListener
mục Danh sách của bạn sẽ báo hiệu bắt đầu kéo.
Trong Gist đó, họ đặt cho người nghe một phần cụ thể trong bố cục của Mục Danh sách ("tay cầm" của mục), do đó người ta không vô tình di chuyển nó bằng cách nhấn bất kỳ phần nào của nó. Cá nhân, tôi thích đi với một onLongClickListener
thay thế, nhưng đó là tùy thuộc vào bạn để quyết định. Đây là một đoạn trích của phần đó:
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;
}
}
Điều này cũng bao gồm việc thêm một onTouchListener
đến ListView
, mà kiểm tra nếu một mục đang được kéo, tay cầm những trao đổi và huỷ bỏ hiệu lực, và dừng lại tình trạng kéo. Một đoạn trích của phần đó:
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;
}
});
Cuối cùng, đây là cách stopDrag
và startDrag
các phương thức trông như thế nào, xử lý việc kích hoạt và vô hiệu hóa quá trình kéo:
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}