it-swarm.com.de

Android GridView ordnet Elemente per Drag and Drop neu an

Ich habe eine GridView in einer Anwendung, an der ich gerade arbeite. Ich möchte die Elemente in der GridView per Drag & Drop neu anordnen können. Ich habe viel Hilfe für ListViews gefunden, aber nichts für GridViews. Ich möchte ein Verhalten wie in dieser Launcher-App http://www.youtube.com/watch?v=u5LISE8BU_E&t=5m30s erzielen. Irgendwelche Ideen?

27
Martin C.

Wenn Sie dieses Problem nicht beheben, gebe ich meinen Code an. Aber es funktioniert auf Android 3.0 und höher, weil ich 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;

und 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;
}

Ich hoffe es hilft dir

23

Meine Version zum Ziehen und Ablegen der Rasteransicht https://github.com/askerov/DynamicGrid .
Er erweitert das ursprüngliche GridView, unterstützt das Ziehen und Ablegen, um die Elemente neu anzuordnen. Es ist voll funktionsfähig auf Version 3.0 und höher, unterstützt jedoch 2.2 und 2.3 mit Einschränkungen (keine Animationen).

7
Alex Askerov

Werfen Sie einen Blick auf thquinns DraggableGridView , Dies wurde für Android 2.2 (API Level 8) entwickelt.

2
vin

Es ist nicht leicht, eine kurze Antwort darauf zu geben, da es Hunderte von Codezeilen gibt: Sie müssen den Start der Ziehaktion abfangen, normalerweise onLongClick, die Ansicht ausblenden, die die Aktion ausgelöst hat, und eine Overlay anzeigen, die verschoben werden kann während sich der Benutzer noch in der Touchdown-Aktion befindet, und nehmen Sie die Änderungen schließlich beim Touch-Up vor. Am besten erweitern Sie den Standard GridView in Android.widget. Das Ergebnis sieht so aus:

enter image description here

Hier ist eine Youtube-Video-Demo, die Sie möglicherweise nützlich finden: http://www.youtube.com/watch?v=m4yktX3SWSs&feature=youtu.be

Ich habe auch eine ausführlichere Antwort in einem Artikel auf meinem Blog zusammengestellt. Vielleicht finden Sie es nützlich, da es ein komplettes Beispiel für den Quellcode enthält. Der Link lautet: http://www.pocketmagic.net/2013/11/complex-Android-gridview-mit-drag-und-drop-funktionalität/

1
radhoo

Mit Hilfe des Drag-and-Drop-Frameworks verwende ich anstelle des Umlaufens der untergeordneten Elemente und Festlegen des Draglisteners einen Layout-Container für Rasterelemente, einen DragableLinearLayout, der das LinearLayout erweitert und die onDragEvent (DragEvent) -Methode implementiert. 

So können Sie Ihr Raster wie üblich mit dem Adapter füllen, und der größte Teil des Drag & Drop-Codes befindet sich im onDragEvent von 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;
    }
};
1
ac19

Ich habe kürzlich eine Lösung gefunden, für die der Autor einige Zeit hier verbracht hat http://blahti.wordpress.com/2012/03/03/improved-drag-drop-for-gridview/ Es gibt 4 Vorhergehende verwandte Blogbeiträge, in denen detailliert beschrieben wird, was dort vor sich geht.

0
jJ'

Wahrscheinlich ist das PagedDragDropGrid-Projekt genau das, was Sie brauchen: https://github.com/mrKlar/PagedDragDropGrid

Es bietet benutzerdefinierte ViewGroup (ähnlich wie GridView) mit Funktionen für die reibungslose Neuordnung (genau wie in Ihrem Video). Wahrscheinlich erfordert es ein paar Anpassungen, aber es lohnt sich.

Ich hoffe es hilft.

0
Andrei Buneyeu

Hier ist eine bibliothek von h6ah4i, die die Recycler-Ansichten nutzt, um eine Drag-and-Drop-Rasteransicht mit Nachordnungsfunktionen bereitzustellen.

0
Cody Pinto

Google hat vor einigen Monaten einige Code Labs veröffentlicht. https://codelabs.developers.google.com/codelabs/Android-training-adaptive-layouts/index.html?index=..%2F..%2Fandroid-training#

Sie können die Lösung dafür hier überprüfen https://github.com/google-developer-training/Android-fundamentals-apps-v2/tree/master/MaterialMe-Resource

Sie erstellen ein Rasterlayout mit beweglichen Karten, die mit dem itemTouchHandler an eine beliebige Stelle im Layout gezogen und dort abgelegt werden können.

Der detailliertere Code für das Ziehen und Ablegen lautet hier . Sie müssen sich mit Aufgabe 3: Machen Sie Ihre CardView schwenkbar, beweglich, und anklickbar Abschnitt

0
Ebrahim Karam