У меня есть список записей в списке, который я хочу, чтобы пользователь мог повторно сортировать, используя метод перетаскивания. Я видел, как это реализовано в других приложениях, но я не нашел для него учебника. Это должно быть то, что нужно другим. Может ли кто-нибудь указать мне код для этого?
Ответ 1
Я работаю над этим в течение некоторого времени. Трудно получить право, и я не утверждаю, что знаю, но доволен этим до сих пор. Мой код и несколько демонстраций можно найти в
Его использование очень похоже на TouchInterceptor (на котором основан код), хотя были сделаны значительные изменения в реализации.
DragSortListView имеет плавную и предсказуемую прокрутку при перетаскивании и перемещении элементов. Перетасовка элементов намного более согласована с положением элемента перетаскивания/плавания. Поддерживаются элементы списка разнородных высот. Drag-scrolling настраивается (я демонстрирую быстрое перетаскивание прокрутки по длинному списку - не то, что приложение приходит на ум). Верхние и нижние колонтитулы соблюдаются. и т.д.?? Посмотрите.
Ответ 2
Добавляю этот ответ для тех, кто говорит об этом.
В последнее время произошел эпизод DevBytes (Перетаскивание и преобразование ячеек ListView), в котором объясняется, как это сделать
Вы можете найти здесь здесь также доступен пример кода здесь.
Что этот код в основном делает, так это то, что он создает dynamic listview
расширением listview
, которое поддерживает перетаскивание и замену ячеек. Чтобы вы могли использовать DynamicListView
вместо вашего основного listview
и что вы внедрили ListView с перетаскиванием.
Ответ 3
Теперь это довольно легко реализовать для RecyclerView
с ItemTouchHelper. Просто переопределите метод onMove
из ItemTouchHelper.Callback
:
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
mMovieAdapter.swap(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
Довольно хорошее руководство по этому вопросу можно найти на сайте medium.com: Перетаскивание и прокрутка с помощью RecyclerView
Ответ 4
Я нашел DragSortListView работал хорошо, хотя начать с него было проще. Вот краткий учебник по использованию его в Android Studio со списком в памяти:
-
Добавьте это в зависимости
build.gradle
для вашего приложения:compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
-
Создайте ресурс для идентификатора дескриптора перетаскивания, создав или добавив в
values/ids.xml
:<resources> ... possibly other resources ... <item type="id" name="drag_handle" /> </resources>
-
Создайте макет для элемента списка, который содержит ваше любимое изображение с ручкой перетаскивания, и назначьте его ID ID, который вы создали на шаге 2 (например,
drag_handle
). -
Создайте макет DragSortListView, примерно так:
<com.mobeta.android.dslv.DragSortListView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dslv="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" dslv:drag_handle_id="@id/drag_handle" dslv:float_background_color="@android:color/background_light"/>
-
Задайте производную
ArrayAdapter
с переопределениемgetView
, которое отобразит ваш элемент списка.final ArrayAdapter<MyItem> itemAdapter = new ArrayAdapter<MyItem>(this, R.layout.my_item, R.id.my_item_name, items) { // The third parameter works around ugly Android legacy. http://stackoverflow.com/a/18529511/145173 @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); MyItem item = getItem(position); ((TextView) view.findViewById(R.id.my_item_name)).setText(item.getName()); // ... Fill in other views ... return view; } }; dragSortListView.setAdapter(itemAdapter);
-
Установите прослушиватель кавычек, который переупорядочивает элементы по мере их удаления.
dragSortListView.setDropListener(new DragSortListView.DropListener() { @Override public void drop(int from, int to) { MyItem movedItem = items.get(from); items.remove(from); if (from > to) --from; items.add(to, movedItem); itemAdapter.notifyDataSetChanged(); } });
Ответ 5
Библиотека DragListView делает это очень аккуратно с очень приятной поддержкой пользовательских анимаций, таких как анимация возвышения. Он также по-прежнему поддерживается и обновляется на регулярной основе.
Вот как вы его используете:
1: сначала добавьте lib в gradle
зависимости { compile 'com.github.woxthebox: draglistview: 1.2.1'
}
Код>
2: Добавить список из xml
<Предварительно > <код > < com.woxthebox.draglistview.DragListView андроид: идентификатор = "@+ идентификатор /draglistview " андроид: layout_width = "match_parent" Android: layout_height = "match_parent" / > Код >3: Установите прослушиватель перетаскивания
mDragListView.setDragListListener(новый DragListView.DragListListener() { @Override public void onItemDragStarted (int position) { }
@Override public void onItemDragEnded (int fromPosition, int toPosition) { }
});
Код>
4: Создайте адаптер, переопределенный с помощью DragItemAdapter
public class ItemAdapter расширяет DragItemAdapter < Pair < Long, String >, ItemAdapter.ViewHolder > public ItemAdapter (ArrayList < Pair < Long, String > > список, int layoutId, int grabHandleId, boolean dragOnLongPress) { супер (dragOnLongPress); mLayoutId = layoutId; mGrabHandleId = grabHandleId; setHasStableIds (истинный); setItemList (список);
}
Код>
5: Внедрите зрителя, который простирается от DragItemAdapter.ViewHolder
открытый класс ViewHolder расширяет DragItemAdapter.ViewHolder { public TextView mText;
public ViewHolder (final View itemView) { super (itemView, mGrabHandleId); mText = (TextView) itemView.findViewById(R.id.text); }
@Override public void onItemClicked (View view) { }
@Override public boolean onItemLongClicked (Просмотреть представление) { return true; }
}
Код>
Для получения более подробной информации перейдите на страницу https://github.com/woxblom/DragListView
Ответ 6
Недавно я наткнулся на эту замечательную Gist, которая дает рабочую реализацию сортировки перетаскивания ListView
, без каких-либо внешних зависимостей.
В основном это заключается в том, что ваш пользовательский адаптер расширяется ArrayAdapter
как внутренний класс для активности, содержащей ваш ListView
. На этом адаптере затем устанавливается onTouchListener
на ваши элементы списка, которые будут сигнализировать о начале перетаскивания.
В этом Gist они устанавливают слушателя на определенную часть макета элемента списка ( "дескриптор" элемента), поэтому его нельзя случайно переместить, нажав любую его часть. Лично я предпочел пойти с onLongClickListener
вместо этого, но это зависит от вас, чтобы решить. Вот выдержка из этой части:
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;
}
}
Это также связано с добавлением onTouchListener
в ListView
, который проверяет, перетаскивается ли элемент, обрабатывает подкачку и недействительность и останавливает состояние перетаскивания. Выдержка из этой части:
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 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;
}
});
Наконец, вот как выглядят методы stopDrag
и startDrag
, которые обрабатывают включение и отключение процесса перетаскивания:
public void startDrag(String string) {
mPosition = -1;
mSortable = true;
mDragString = string;
mAdapter.notifyDataSetChanged();
}
public void stopDrag() {
mPosition = -1;
mSortable = false;
mDragString = null;
mAdapter.notifyDataSetChanged();
}