Wie beschränke ich den Drag & Drop entlang der y-Achse nur in Android?

Ich versuche, die Drag & Drop-Bewegung auf nur die Y-Achse zu beschränken, damit ein Benutzer nur eine Ansicht machen und ihn nach oben oder unten ziehen kann – nicht links oder rechts.

Ich habe jetzt zwei Ansichten (ids of textView und dropZone). Ein (TextView) hat einen Touch-Listener, der darauf eingestellt ist, und ein anderer (dropZone) hat einen Drag-Listener, der darauf eingestellt ist.

Hier ist das Layout xml (activity_main.xml):

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="50dp" android:background="#FFFFFF00" android:text="Text Drag" /> <TextView android:id="@+id/dropZone" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="167dp" android:background="#FFFF0000" android:text="Drop Zone" /> </RelativeLayout> 

Im Folgenden ist der Aktivitätscode:

 package com.example.dragexperiment; import android.app.Activity; import android.content.ClipData; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.DragEvent; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.View.DragShadowBuilder; import android.view.View.OnDragListener; import android.view.View.OnGenericMotionListener; import android.view.View.OnTouchListener; import android.widget.RelativeLayout; import android.widget.TextView; public class MainActivity extends Activity { TextView tv, dz, sv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.textView); dz = (TextView) findViewById(R.id.dropZone); tv.setOnTouchListener(new MyTouchListener()); dz.setOnDragListener(new MyDragListener()); } private final class MyTouchListener implements OnTouchListener { int viewX0, viewY0, cY0, cY1, deltaCursorY; @Override public boolean onTouch(final View v,final MotionEvent event) { switch(event.getAction()) { case MotionEvent.ACTION_DOWN: viewX0 = (int) v.getX(); viewY0 = (int) v.getY(); cY0 = (int) event.getRawY(); ClipData data = ClipData.newPlainText("", ""); DragShadowBuilder shadow = new View.DragShadowBuilder(v); v.startDrag(data, shadow, v, 0); return true; case MotionEvent.ACTION_MOVE: // cY1 = (int) event.getRawY(); // deltaCursorY = cY1 - cY0; // v.setX(viewX0); // v.setY(viewY0 + deltaCursorY); return true; } return false; } } class MyDragListener implements OnDragListener { public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: break; case DragEvent.ACTION_DRAG_ENTERED: v.setBackgroundColor(Color.BLUE); break; case DragEvent.ACTION_DRAG_EXITED: break; case DragEvent.ACTION_DROP: v.setBackgroundColor(Color.BLUE); break; case DragEvent.ACTION_DRAG_ENDED: break; default: break; } return true; } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } 

Wie Sie aus dem oben genannten Code sehen können, wenn ein Benutzer textView über dropZone zieht, versuche ich, die dropZone View Hintergrundfarbe auf blau zu drehen. Das funktioniert gut, wenn ich einen DragShadowBuilder im ACTION_DOWN-Bewegungsereignis verwende:

  ClipData data = ClipData.newPlainText("", ""); DragShadowBuilder shadow = new View.DragShadowBuilder(v); v.startDrag(data, shadow, v, 0); 

Das Problem ist, dass ich den Schatten nicht kontrollieren kann, so dass er sich nur entlang der Y-Achse (vertikale) Achse bewegt.

Wenn ich den DragShadowBuilder-Code (die drei Zeilen oben) herausnehme und den Code hinzufüge, um die gezogene Ansicht im ACTION_MOVE-Bewegungsereignis zu verschieben (es ist oben kommentiert):

  cY1 = (int) event.getRawY(); deltaCursorY = cY1 - cY0; v.setX(viewX0); v.setY(viewY0 + deltaCursorY); 

Dann kann ich das TextView kontrollieren, um sich nur entlang der Y-Achse zu bewegen. Leider, ohne einen DragShadowBuilder, kann ich nicht die ACTION_DRAG_ENTERED DragEvent auslösen, um die dropZone-Ansicht blau zu drehen.

Wenn ich sowohl den DragShadowBuilder-Code als auch die vier Zeilen Code hinterlasse, wird das ACTION_MOVE-Bewegungsereignis nur einmal für einen Drag ausgelöst; Es geht nicht weiter nach hinten.

Jemand hat irgendwelche Ideen, was ich tun kann? Ich habe das schon seit einiger Zeit herumgearbeitet, aber ohne Glück. Ich habe sogar an einem Punkt versucht, eine benutzerdefinierte Ansicht zu erstellen, die die Android View-Klasse erweitert, aber ich kann die startDrag-Methode nicht überschreiben, weil sie als endgültig deklariert ist. Ich wünschte, ich wäre besser hier. 🙁

  • Android imageView: Einstellen von Drag & Pin-Zoom-Parametern
  • Ziehe mehrere Ansichten in einem verschiebbaren Bereich in Android (wie Snapchat)
  • Mit Rotation löschen
  • Drag n Drop Textview in Android
  • Android Drag & Drop getClipData gibt immer null zurück
  • Ziehen von Elementen in gridview
  • Beste Weg, um Elemente in Android 4+ ListView neu zu ordnen
  • Android GridView ordnet Elemente per Drag & Drop an
  • 2 Solutions collect form web for “Wie beschränke ich den Drag & Drop entlang der y-Achse nur in Android?”

    Ah ha! Ich konnte diese Antwort nicht überall finden (und viele Leute fragten), also hier ist was ich tat.

    Die Grundidee war, den DragShadow unsichtbar zu machen und die Y-Achsenbewegung auf die Ansicht zu bringen, die du "ziehen" möchtest. In Wirklichkeit ziehst du den DragShadow, aber es wird dem Benutzer erscheinen, dass die verschiebbare Ansicht verschoben wird.

     draggableItem.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(final View view, MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { ClipData data = ClipData.newPlainText("", ""); View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(new View(getApplicationContext())); view.startDrag(data, shadowBuilder, view, 0); return true; } else { return false; } } }); mDropZone.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: ViewGroup.MarginLayoutParams lParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams(); _yDelta = (int) event.getY() - lParams.topMargin; break; case DragEvent.ACTION_DRAG_LOCATION: ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) arcMenu.getLayoutParams(); layoutParams.topMargin = (int) event.getY() - _yDelta; arcMenu.setLayoutParams(layoutParams); break; case DragEvent.ACTION_DROP: // Dropped, reassign View to ViewGroup View view = (View) event.getLocalState(); // Do your drop actions here view.setVisibility(View.VISIBLE); break; default: break; } return true; } }); 

    Sie müssen auch die Variable _yDelta in Ihrer Klasse deklarieren.

    Hoffe, das funktioniert für alle Sie cool Katzen da draußen!

    Der folgende Code macht den Schleppschatten unsichtbar, aber immer noch die Sicht sichtbar:

     View transparentView = new FrameLayout(getContext()); DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(transparentView); view.startDrag(data, shadowBuilder, view, 0); 

    Sie können den y-Wert der Ansicht aus dem Drag-Event entsprechend ändern:

     view.setY(event.getY()); 
    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.