Drag and Drop Item wird in die Box gelegt

  • Antworten:23
SilverBlue
  • Forum-Beiträge: 45

31.08.2016, 14:44:18 via Website

Hallo,

ich schaffe es einfach nicht und bräuchte eure Hilfe ;-)

In meinem Code kann der User ein Item in aus einer Box, in einer anderen Box packen (Drag and Drop).

Aber wenn der User das Item in eine Box packt, wo schon ein Item drin ist, wird es einfach dazugefügt.

Ich hätte es jedoch gerne, dass die Items sich tauschen.

    @Override
public boolean onDrag(View v, DragEvent event) {
    switch (event.getAction()) {
        case DragEvent.ACTION_DRAG_STARTED:
            // Do nothing
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            v.setBackground(enterShape);
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            v.setBackground(normalShape);
            break;
        case DragEvent.ACTION_DROP:
            // view dropped, reassign the view to the new ViewGroup
            View view = (View) event.getLocalState();
            ViewGroup owner = (ViewGroup) view.getParent();
            owner.removeView(view);
            LinearLayout container = (LinearLayout) v;
            container.addView(view);
            view.setVisibility(View.VISIBLE);
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            v.setBackground(normalShape);
        default:
            break;
    }
    return true;
}

Antworten
swa00
  • Forum-Beiträge: 3.704

31.08.2016, 15:02:39 via Website

Hallo Silver,

willkommen im Forum ..

Wie wäre es denn , wenn du eine Structurklasse dem Adapter(Liste) übergibst incl. einem unique_id flag und somit das Ganze abfangen kannst.

lg
Stefan

— geändert am 31.08.2016, 15:06:13

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
SilverBlue
  • Forum-Beiträge: 45

31.08.2016, 15:20:00 via Website

Ich muss zugeben, dass ich erst seit ca. einer Woche in Java und Android programmiere :-( Könntest Du mir evtl. ein kleines Beispiel geben, wie ich das bewerkstelligen kann? ;-)

Antworten
swa00
  • Forum-Beiträge: 3.704

31.08.2016, 15:34:07 via Website

Zuerst mal zwei Fragen :

Du arbeitest doch sicherlich mit einem Adapter - richtig ??
Dem übergibst du doch den Content - richtig ?? (z.b. ArrayList)

Liebe Grüße - Stefan
[ App - Entwicklung ]

Antworten
SilverBlue
  • Forum-Beiträge: 45

31.08.2016, 17:22:07 via Website

ähm, ich glaube nein. Jedenfalls kann ich hier keinen Array erkennen :-/ Einen Adapter nutze ich nicht

   OnTouchListener dragListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            // start move on a touch event
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                ClipData data = ClipData.newPlainText("", "");
                DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
                view.startDrag(data, shadowBuilder, view, 0);
                view.setVisibility(View.VISIBLE);
                return true;
            }
            return false;

        }
    };

Ich würde ein If-Statement einfügen, was überprüft, ob die Box leer ist. Wenn sie leer ist, kann der Code so wie meiner laufen, ansonsten wird das aktuelle Item mit dem anderen aus der Box getauscht. Leider weiß ich A) nicht, wo ich die Struktur einfügen soll und B) nicht, wie ich überprüfen kann, ob die Box leer ist und wie der Inhalt genau ist.

— geändert am 31.08.2016, 17:33:49

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

31.08.2016, 18:05:13 via Website

Man kann es mit Struktur Logik dahinter machen, macht es aber durchaus aufwändiger, musst du entscheiden wie du es haben willst.
Um erstmal auf funktionaler Ebene zu bleiben:
1. Woher hast du den Code? Wenn du noch nicht lange Programmiert dann ist das Werk sicher nicht dein eigen ;)
2. Du kannst es doch einfach prüfen ob die View (ViewGroup) schon Childs (andere Views ) hat.
https://developer.android.com/reference/android/view/ViewGroup.html#getChildCount()
Diese Info musst du dann in der if verarbeiten und je nach ergebnis weiter verfahren.
Also evntl nur hinzufügen oder Views tauschen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

31.08.2016, 18:13:31 via Website

Ich den Code aus diesem Tutorial hier: vogella.com/tutorials/AndroidDragAndDrop/article.html

Kann gerade leider nichts austesten, werde mich gleich aber mal an die Arbeit machen und versuchen mit getChildCount zu überprüfen, ob die Box leer ist.

Antworten
SilverBlue
  • Forum-Beiträge: 45

01.09.2016, 13:43:33 via Website

hm... ich bekomme einfach keine funktionierende If-Abfrage hin :-(

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

01.09.2016, 14:17:12 via Website

Du musst erstmal lernen, wie man debuggt.
Dann kannst ud dir deine Variablen/Views (deren Daten und childCounts etc..) zur laufzeit im Debugger anschauen, dann weißt du auch wie du deine If basteln musst

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

01.09.2016, 17:29:53 via Website

Mitlerweile habe ich hinbekommen, dass ich erkennen kann, welches Item wohin gesetzt wurde. Allerdings schaffe ich es immer noch nicht zu erkennen, wie ich herausbekomme, ob die Box bereits mit einem Item gefüllt ist oder nicht :-/

case DragEvent.ACTION_DROP:
            // view dropped, reassign the view to the new ViewGroup
            View view = (View) event.getLocalState();
            ViewGroup owner = (ViewGroup) view.getParent();
            owner.removeView(view);
            LinearLayout container = (LinearLayout) v;
            container.addView(view);
            view.setVisibility(View.VISIBLE);
            switch (view.getId()) {
                case R.id.imgBtnItem1:
                    Toast.makeText(UserArea.this, "Item 1 verschoben", Toast.LENGTH_SHORT).show();
            }
            switch (v.getId()) {
                case R.id.box6:
                    Toast.makeText(UserArea.this, "Irgendein Item wurde in Box 6 verschoben", Toast.LENGTH_SHORT).show();
            }
            break;

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

01.09.2016, 17:31:54 via Website

Vielleicht solltest du den Views mal aussagekräftige Variablennamen geben.
Welche view ist die ViewGroup in welche du es ziehtst und welche ist die gezogenen View?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

01.09.2016, 17:39:00 via Website

View ist das Item
v ist die Box

Ich möchte ja eigentlich nur, dass:
Wenn in der Box (v) schon ein Item (View) ist, dann tausche beide Items aus. Wo Item 1 war, ist jetzt Item 2.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

01.09.2016, 18:20:29 via Website

Wenn mcih nicht alles täcut müsste das doch so umzusetzen sein:

Wenn Box->hasChilds => Schon was drin dann Box-> removeChilds/ aber in varaiable speichern.
und dann BOX-> addChild (Item)
und jetzt muss du nur issen aus welcher Box das Item kan umd dann kannst du das Item was du gerade entfernnt hast da hinzufügen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

01.09.2016, 18:39:31 via Website

Sehr gut, das hat mich schon wieder einen Schritt weiter gebracht, vielen Dank ;-)

Ich erkenne jetzt, ob bereits ein Item in der Box ist, also ob die Box Kinder hat :-) Wenn das Item in eine Box geschoben wird, wo bereits ein Item ist, passiert aktuell nichts. Vielleicht kann man da ansetzen...

Jetzt muss ich nur irgendwie in case 2 reinbekommen, dass sich die Items austauschen...

Hier mal mein komplettes DragEvent:

case DragEvent.ACTION_DROP:
            View view = (View) event.getLocalState();
            ViewGroup owner = (ViewGroup) view.getParent();
            LinearLayout container = (LinearLayout) v;


            switch (container.getChildCount()) {
                case 0:
                    Toast.makeText(UserArea.this, "0 Kinder", Toast.LENGTH_SHORT).show();
                    owner.removeView(view);
                    container.addView(view);
                    break;
                case 1:
                    Toast.makeText(UserArea.this, "1 Kinder", Toast.LENGTH_SHORT).show();
                    break;
            }
            break;

— geändert am 01.09.2016, 18:58:13

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

01.09.2016, 18:59:49 via Website

Das ist ja auch nicht so kompliziert:
Wenn Box schon belegt, dann view die da drin ist in variable speichern und "Kind" rauslöschen.
Dann neues Item einfügen.
Zudem musst du noch speichern, aus welcher box dein Verschobenens Item kommt, in diese kannst du dann die andere View hinzufügen

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

01.09.2016, 19:08:55 via Website

Okay, da setze ich mich aber morgen dran. Es liest sich einfacher als es ist, denn ich kann irgendwie nicht unterscheiden, was von den Variablen jetzt das aktuelle Item und was das "Ursprung-Item" ist. Werde auch die Variablen mal sinngemäßer umbenennen, vielleicht wird es dann auch einfacher ;-)

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

01.09.2016, 19:54:37 via Website

Das macht es sicher einfacher, dann behält man die Übersicht

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

06.09.2016, 19:41:59 via Website

Ich habe jetzt hin und her probiert, bin aber zu keinem funktionierenden Ergebnis gekommen :-(

Hier ist der Codebaustein, der dafür verantwortlich sein sollte:

switch (Neu.getChildCount()) {
                case 0:
                    Toast.makeText(UserArea.this, "0 Kinder", Toast.LENGTH_SHORT).show();
                    Ursprung.removeView(Item);
                    Neu.addView(Item);
                    break;
                case 1:
                    Toast.makeText(UserArea.this, "1 Kinder ", Toast.LENGTH_SHORT).show();
                    break;
            }
            break;

0 Kinder bedeutet, es ist nichts in der Box drin. 1 Kinder bedeutet, es ist ein Item drin.

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

06.09.2016, 19:51:31 via Website

Die Toast funktionieren und passen auch zu deinen Aktionen oder?
Jetzt musst du dir halt eine Logik sucen, das "Kind" aus dem View "Neu" zu entfernen und in die Box legen wo das Item herkommt. Das dürfte doch an sich nicht so schwer sein.
Aber wenn du nicht schreibst, wo genau es hakt, dann kann ich dir auch nicht helfen.
Die Fertige Lösung kenne ich auch nicht, in kleinen Schritten kommt man zum Ziel ;)

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

06.09.2016, 19:59:37 via Website

Die Toasts funktionieren sehr gut, ja.

Mit Box.getId() bekomme ich die ID des Items heraus, welches ich gerade in der Hand habe. Allerdings kann ich nicht herausfinden, welches Item gerade in der Box drin ist.

Hier nochmal die ganze Action_DROP:

case DragEvent.ACTION_DROP:
            View Item = (View) event.getLocalState();
            ViewGroup Ursprung = (ViewGroup) Item.getParent();
            LinearLayout Neu = (LinearLayout) Box;

            switch (Box.getId()) {
                case R.id.ressourcen_box_papierkorb:
                    Toast.makeText(UserArea.this, "Item wurde gelöscht", Toast.LENGTH_SHORT).show();
                    Ursprung.removeView(Item);
                    Item.setVisibility(View.INVISIBLE);
                    break;
            }


            switch (Neu.getChildCount()) {
                case 0:
                    Toast.makeText(UserArea.this, "0 Kinder", Toast.LENGTH_SHORT).show();
                    Ursprung.removeView(Item);
                    Neu.addView(Item);
                    break;
                case 1:
                    Toast.makeText(UserArea.this, "1 Kinder ", Toast.LENGTH_SHORT).show();
                    break;
            }
            break;

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

06.09.2016, 20:28:27 via Website

Natürlich kannst du das, du musst dir dann sozusagen alle "Kinder" anschauen. Wenn das Layout nicht zu kompliziert ist dann sollte man das item leicht finden.:
Hiermit kannst zu z.b. durch alle "Kinder" durchiterieren:
int count = layout.getChildCount();
View v = null;
for(int i=0; i v = layout.getChildAt(i);
//do something with your child element
}
Dann musst du nurnoch wissen auf welcher Ebene dein item in der Box ist und dann kannst du es über View#getChildAt(..) auslesen und weiterverarbeiten und dann aus der ursprünglichen Box entfernen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

07.09.2016, 15:29:29 via Website

Was mir noch nicht einleuchtet, wie erkennt die For-Schleife das Item, welches ausgetauscht werden soll?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

07.09.2016, 15:30:55 via Website

Garnicht, du musst spezifizieren, was deine Box ist. Sei es über die ID oder über einen gewissen ViewTyp der als Box dient o.ä...
Da musst du dir schon was einfalssen lassen

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
SilverBlue
  • Forum-Beiträge: 45

07.09.2016, 15:33:51 via Website

Okay, ich arbeite dann mal weiter an meinem Projekt. Vielleicht fällt mir zwischendurch eine Lösung ein. Zum Glück ist es nur ein klitzekleines Problemchen :-D

Antworten