Перегляд списку перетягування списку Android


132

У мене є список записів на listview, який я хочу, щоб користувач міг переставити сортування за допомогою методу перетягування. Я бачив це в інших програмах, але не знайшов підручника для цього. Це повинно бути те, що потрібно і іншим. Чи може хтось вказати мені на якийсь код для цього?


1
Я знайшов цей підручник, який може допомогти скласти список сортування . Я ще не тестував її, але відео виглядає багатообіцяючим
Алекс

@Arkde не жартує, через рік вони все ще не прийняли відповіді на це питання.
ArtOfWarfare

@ArtOfWarfare Я думаю, слід врахувати, що з листом, що стався, може трапитися щось нещасне ... забороняючи подальшу діяльність.
heycosmo

1
@heycosmo Цілком можливо ... за їхнім профілем SO, miannelle востаннє відвідував лише місяць після того, як задав питання. Крім того, велика робота над DSLV ... Я вніс декілька змін до нього, щоб дозволити такі речі, як подвійне торкання, щоб дублювати елементи та змінювати тінь елемента, коли він перетягується (кожен мій елемент має свій номер рядка на них, тому я зробив так, що оновлення номерів рядків можуть оновлюватися в міру перетягування.) Вони начебто просто зламані, набагато менш елегантні, ніж все в класі, тому я не подав зміни до GitHub.
ArtOfWarfare

github.com/bauerca/drag-sort-listview Я використовую це і чи можна перетягувати ROW onLongClick of Listview?
Ахін

Відповіді:


85

Я над цим працюю вже деякий час. Важко виправитись, і я не претендую на це, але поки що задоволений цим. Мій код та кілька демонстраційних версій можна знайти на сайті

Його використання дуже схоже на TouchInterceptor (на якому базується код), хоча суттєві зміни в впровадженні внесені.

DragSortListView має плавне та передбачуване прокручування під час перетягування та переміщення елементів. Переміщення предметів набагато більше відповідає позиції предмета, що перетягується / плаває. Підтримуються елементи гетерогенної висоти. Перетягування можна перетягувати (я демонструю швидке прокручування перетягування через довгий список --- не те, що програма приходить на думку). Заголовки / колонтитули поважаються. тощо. ?? Поглянь.


3
Ваше рішення працює як шарм. Набагато краще, ніж інші. Що таке ліцензія вашого вихідного коду? Apache 2.0?
Даріуш Бачинський

1
@heycosmo У мене є кілька проблем при створенні макета в моєму додатку з використанням представлених представлень на демонстраційній версії. Помилка декількох просторів імен. Чи можете ви, можливо, зробити невеликий поштовий блог про те, як використовувати наданий вами код?
daniel_c05

Чи є можливість змінити код таким чином, щоб елементи сортувались не лише по краплях, поки ви перетягуєте предмет над ними?
Олексій Семенюк

@heycosmo Чи можете ви зробити доступ до свого сховища GitHub? Здається, офлайн ...
sdasdadas

8
Бауерка-репо більше не підтримується. Ця вилка активніша: github.com/JayH5/drag-sort-listview
ecdpalma

21

Зараз це досить просто реалізувати за 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;
}

Досить хороший підручник з цього питання можна знайти на сайті media.com: Перетягніть пальцем з RecyclerView


18

Додаю цю відповідь для тих, хто з цього приводу google ..

Нещодавно був епізод DevBytes ( ListView перетягування та перестановка клітин ), який пояснює, як це зробити

Ви можете знайти його тут, також зразок коду доступний тут .

Що в основному цей код робить, це те, що він створює dynamic listviewрозширення, listviewяке підтримує перетягування та заміну клітинок. Так що ви можете використовувати DynamicListViewзамість основного, ListView і ось ви реалізували ListView з перетягуванням.


1
Під час використання програми DevBytes майте на увазі, що ваш адаптер та гриб DynamicListView мають один і той же екземпляр, якщо об’єкти масивуються. Інакше реалізація не буде працювати. Це не є проблемою для статичних списків, але це може бути проблемою з навантажувачами
AAverin

Я спробував приклад на поточній версії Android 5.0. Зараз у нього є деякі проблеми ...
Торстен B

@TCA Так, у мене також виникли проблеми на 5.0. Будь ласка, допоможіть.
Ману

6

Вкладка DragListView робить це дійсно акуратно з дуже приємною підтримкою для користувацьких анімацій, таких як анімація висоти. Він також все ще підтримується та оновлюється регулярно.

Ось як ви його використовуєте:

1: Спершу додайте кришку до градле

dependencies {
    compile 'com.github.woxthebox:draglistview:1.2.1'
}

2: Додати список із xml

<com.woxthebox.draglistview.DragListView
    android:id="@+id/draglistview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

3: Встановити прослуховувач перетягування

mDragListView.setDragListListener(new DragListView.DragListListener() {
    @Override
    public void onItemDragStarted(int position) {
    }

    @Override
    public void onItemDragEnded(int fromPosition, int toPosition) {
    }
});

4: Створіть адаптер, замінений на DragItemAdapter

public class ItemAdapter extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder>
    public ItemAdapter(ArrayList<Pair<Long, String>> list, int layoutId, int grabHandleId, boolean dragOnLongPress) {
        super(dragOnLongPress);
        mLayoutId = layoutId;
        mGrabHandleId = grabHandleId;
        setHasStableIds(true);
        setItemList(list);
}

5: Вкажіть програму перегляду, яка поширюється на DragItemAdapter.ViewHolder

public class ViewHolder extends 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(View view) {
        return true;
    }
}

Для отримання більш детальної інформації відвідайте https://github.com/woxblom/DragListView


5

Я виявив, що DragSortListView добре працював, хоча почати роботу можна було і простіше. Ось короткий посібник щодо його використання в Android Studio зі списком пам’яті:

  1. Додайте це до build.gradleзалежностей для вашої програми:

    compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
  2. Створіть ресурс для ідентифікатора ручки перетягування, створивши або додавши до values/ids.xml:

    <resources>
        ... possibly other resources ...
        <item type="id" name="drag_handle" />
    </resources>
  3. Створіть макет для елемента списку, який включає улюблене зображення ручки перетягування, і призначте його ідентифікатор ідентифікатору, який ви створили на кроці 2 (наприклад drag_handle).

  4. Створіть макет 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"/>
  5. Встановіть 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);
  6. Встановіть прослуховувач крапель, який буде переставляти елементи під час їх скидання.

        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();
            }
        });

3

Нещодавно я натрапив на цю велику істоту, яка дає діючу реалізацію перетягування 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'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;
    }
});

Нарешті, ось, як виглядають методи 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();
}

Хоча це здається однією з найпростіших реалізацій, це виглядає погано (рядки просто перемикаються, насправді нуль виглядає), почуває себе погано і робить прокрутку списку, який не підходить до екрана майже неможливо (я постійно перемикаю рядки замість прокручування).
Хайнцльман
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.