Android GridView изменить порядок элементов с помощью перетаскивания - PullRequest
27 голосов
/ 22 августа 2011

У меня есть приложение GridView в приложении, над которым я работаю. Я хотел бы иметь возможность изменить порядок элементов в GridView с помощью перетаскивания. Я нашел много помощи для ListViews, но ничего о GridViews. Я хочу добиться поведения, как в этом приложении запуска http://www.youtube.com/watch?v=u5LISE8BU_E&t=5m30s. Есть идеи?

Ответы [ 9 ]

23 голосов
/ 14 сентября 2011

Если вы не решите эту проблему, я предоставлю свой код.Но это работает на Android 3.0 и выше, потому что я использую android drag-n-drop framework

grid = (GridView) findViewById(R.id.grid);
grid.setAdapter(new DragGridAdapter(items, getActivity()));

....

grid.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                GridView parent = (GridView) v;

                int x = (int) event.getX();
                int y = (int) event.getY();

                int position = parent.pointToPosition(x, y);
                if (position > AdapterView.INVALID_POSITION) {

                    int count = parent.getChildCount();
                    for (int i = 0; i < count; i++) {
                        View curr = parent.getChildAt(i);
                        curr.setOnDragListener(new View.OnDragListener() {

                            @Override
                            public boolean onDrag(View v, DragEvent event) {

                                boolean result = true;
                                int action = event.getAction();
                                switch (action) {
                                case DragEvent.ACTION_DRAG_STARTED:
                                    break;
                                case DragEvent.ACTION_DRAG_LOCATION:
                                    break;
                                case DragEvent.ACTION_DRAG_ENTERED:
                                    v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_selected);
                                    break;
                                case DragEvent.ACTION_DRAG_EXITED:
                                    v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected);
                                    break;
                                case DragEvent.ACTION_DROP:
                                    if (event.getLocalState() == v) {
                                        result = false;
                                    } else {
                                        View droped = (View) event.getLocalState();
                                        GridItem dropItem = ((DragGridItemHolder) droped.getTag()).item;

                                        GridView parent = (GridView) droped.getParent();
                                        DragGridAdapter adapter = (DragGridAdapter) parent.getAdapter();
                                        List<GridItem> items = adapter.getItems();

                                        View target = v;
                                        GridItem targetItem = ((DragGridItemHolder) target.getTag()).item;
                                        int index = items.indexOf(targetItem);
                                        items.remove(dropItem);
                                        items.add(index, dropItem);
                                        adapter.notifyDataSetChanged();
                                    }
                                    break;
                                case DragEvent.ACTION_DRAG_ENDED:
                                    v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected);
                                    break;
                                default:
                                    result = false;
                                    break;
                                }
                                return result;
                            }
                        });
                    }

                    int relativePosition = position - parent.getFirstVisiblePosition();


                    View target = (View) parent.getChildAt(relativePosition);

                    DragGridItemHolder holder = (DragGridItemHolder) target.getTag();
                    GridItem currentItem = holder.item;
                    String text = currentItem.getFile().getAbsolutePath();

                    ClipData data = ClipData.newPlainText("DragData", text);
                    target.startDrag(data, new View.DragShadowBuilder(target), target, 0);
                }
            }
            return false;

и DragGridAdapter

public class DragGridAdapter extends BaseAdapter{
private Context context;
private List<GridItem> items;

public DragGridAdapter(List<GridItem> items, Context context){
    this.context = context;
    this.items = items;
}

@Override
public int getCount() {
    return items.size();
}

@Override
public Object getItem(int position) {
    return items.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    DragGridItemHolder holder;
    if (convertView == null) {
        holder = new DragGridItemHolder();

        ImageView img = new ImageView(context);
        holder.image = img;
        convertView = img;
        convertView.setTag(holder);
    } else {
        holder = (DragGridItemHolder) convertView.getTag();
    }
    holder.item = items.get(position);
    holder.image.setImageBitmap(items.get(position).getBitmap());
    return convertView;
}

public List<GridItem> getItems() {
    return items;
}

Надеюсь, это поможетвы

7 голосов
/ 10 сентября 2013

Моя версия для перетаскивания в виде сетки https://github.com/askerov/DynamicGrid.
Расширяет оригинальный GridView, поддерживает перетаскивание для изменения порядка элементов, автоматическую прокрутку, если перетаскивать из экрана.Он полностью функционален на API 3.0+, но поддерживает 2.2 и 2.3 с ограничениями (без анимации).

2 голосов
/ 03 июля 2012

Взгляните на Thquinn's DraggableGridView , разработанный для Android 2.2 (уровень API 8). Надеюсь, это кому-нибудь поможет:)

1 голос
/ 25 ноября 2013

Непросто дать краткий ответ на это, так как задействованы сотни строк кода: вам нужно будет перехватить начало действия перетаскивания, обычно на onLongClick, скрыть представление, инициировавшее действие, показать наложение, котороеперемещаться, пока пользователь все еще находится в контакте, и, наконец, вносить изменения при касании.Лучший способ - расширить стандартный GridView в android.widget.Результат выглядит следующим образом:

enter image description here

Вот демонстрация видео на YouTube, которая может оказаться вам полезной: http://www.youtube.com/watch?v=m4yktX3SWSs&feature=youtu.be

Я также составил более подробный ответв статье на моем блоге вы можете найти ее полезной, поскольку она содержит полный пример исходного кода.Ссылка: http://www.pocketmagic.net/2013/11/complex-android-gridview-with-drag-and-drop-functionality/

1 голос
/ 20 марта 2012

Используя каркас drag-n-drop, вместо циклического переключения дочерних объектов и установки draglistener, я использую в качестве контейнера макета элемента сетки DragableLinearLayout, который расширяет LinearLayout и реализует метод onDragEvent (DragEvent).

Таким образом, вы можете заполнить свою сетку с помощью адаптера как обычно, и большая часть кода перетаскивания находится в onDragEvent of DragableLinearLayout

public class DragableLinearLayout extends LinearLayout {


    public DragableLinearLayout(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);

    }

    public DragableLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

    }

    public DragableLinearLayout(Context context) {
        super(context);

    }

    @Override
    public boolean onDragEvent(DragEvent event) {
        //in wich grid item am I?
        GridView parent = (GridView) getParent();
        Object item = parent.getAdapter().getItem(
                parent.getPositionForView(this));
            //if you need the database id of your item...
        Cursor cur = (Cursor) item;
        long l_id = cur.getLong(cur.getColumnIndex("youritemid"));

        switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:

            return true;
        case DragEvent.ACTION_DRAG_ENTERED:

            setBackgroundColor(Color.GREEN);
            invalidate();
            return true;
        case DragEvent.ACTION_DRAG_EXITED:
            setBackgroundColor(Color.WHITE);
            invalidate();
            return false;
        case DragEvent.ACTION_DROP:
ClipData cd = event.getClipData();
            long l_id_start = Long.valueOf(cd.getItemAt(0).getText()
                    .toString());
            //
            Toast.makeText(getContext(), "DROP FROM " + l_id_start
                    + " TO " + l_id, Toast.LENGTH_LONG);
            //do your stuff  
                    ........
                    //the db requery will be on the onDragEvent.drop of the container
                    //see the listener


            return false;
        case DragEvent.ACTION_DRAG_ENDED:
            setBackgroundColor(Color.WHITE);
            invalidate();
            //
            return false;

        }

        return true;

    }


}



private View.OnDragListener listenerOnDragEvent = new View.OnDragListener() {

    public boolean onDrag(View v, DragEvent event) {
        // Defines a variable to store the action type for the incoming
        // event
        final int action = event.getAction();
        switch (action) {

        case DragEvent.ACTION_DROP:

            // REQUERY
            updateDbView();
            return false;
            // break;

        }
        return true;
    }
};
0 голосов
/ 20 апреля 2019

Google недавно выпустил несколько кодовых лабораторий несколько месяцев назад. https://codelabs.developers.google.com/codelabs/android-training-adaptive-layouts/index.html?index=..%2F..%2Fandroid-training#0

Вы можете проверить решение здесь https://github.com/google-developer-training/android-fundamentals-apps-v2/tree/master/MaterialMe-Resource

Они создают макет сетки с подвижными карточками, которые можно перетаскивать в любое место макета с помощью itemTouchHandler.

Более подробный код для перетаскивания: здесь Вам нужно взглянуть на Задание 3: сделать ваш CardView смахивающим, подвижным и активируемым раздел

0 голосов
/ 21 мая 2017

Вот библиотека от h6ah4i, которая использует преимущества Recycler Views, чтобы предложить перетаскивание сетки с возможностями переупорядочения.

0 голосов
/ 09 июля 2013

Вероятно, вам нужен проект PagedDragDropGrid: https://github.com/mrKlar/PagedDragDropGrid

Он предоставляет пользовательский ViewGroup (аналог GridView) с функцией плавного изменения порядка (точно так же, как в вашем видео).Возможно, потребуется немного настроек, но оно того стоит.

Надеюсь, это поможет.

0 голосов
/ 13 марта 2012

Я недавно нашел решение, на котором его автор провел довольно много времени здесь http://blahti.wordpress.com/2012/03/03/improved-drag-drop-for-gridview/ Есть 4 предыдущих сообщения в блоге, объясняющих, что там происходит более подробно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...