Trên Android, tôi sử dụng ListView
và tôi muốn có thể sắp xếp lại các mục của nó bằng cách kéo và thả. Tôi biết có sự thực hiện khác nhau của một "kéo và thả listview", tuy nhiên tôi muốn sử dụng Drag and Drop framework đến từ cấp API 11.Kéo và thả, Chế độ xem danh sách và mục bị bỏ lỡ sự kiện ACTION_DRAG_STARTED
Bắt đầu rất tốt cho đến khi tôi muốn cuộn ListView
trong khi thực hiện kéo và thả. Như nó được viết trong ví dụ dưới đây, bây giờ, tôi kiểm tra trên phần tử danh sách nào, vì vậy nếu vị trí của nó không nằm giữa ListView.getLastVisiblePosition()
và ListView.getFirstVisiblePosition()
tôi sử dụng ListView.smoothScrollToPosition()
để xem các mục danh sách khác.
Đây là triển khai đầu tiên nhưng hoạt động khá tốt.
Sự cố phát sinh trong khi cuộn: một số yếu tố không trả lời cho sự kiện kéo và thả - DragEvent.ACTION_DRAG_ENTERED
và các sự kiện khác - khi tôi ở trên đầu chúng. Đó là do cách mà ListView quản lý các khung nhìn item của nó: nó cố gắng tái chế các khung nhìn item mà không nhìn thấy được nữa.
Đó là tất cả các quyền và nó hoạt động, nhưng đôi khi các getView()
của ListAdapter
trả về một đối tượng mới. Vì nó là mới, đối tượng này đã bỏ lỡ DragEvent.ACTION_DRAG_STARTED
vì vậy nó không trả lời các sự kiện DragEvent
khác!
Đây là một ví dụ. Trong trường hợp này, nếu tôi bắt đầu kéo và thả bằng một cú nhấp chuột dài trên một mục danh sách và nếu tôi kéo nó, phần lớn các mục sẽ có nền màu xanh lá cây nếu tôi ở trên đầu chúng; nhưng một số thì không.
Bất kỳ ý tưởng nào về việc khiến họ đăng ký cơ chế sự kiện Kéo và thả ngay cả khi họ bỏ lỡ 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;
}
}
}
tôi không thử loại này nhưng ai biết có thể một ngày nào đó tôi sẽ. Điều này có vẻ là một công việc thực sự tốt, và khá kỹ thuật! Upvote từ tôi. –