title: How do I restrict drag and drop along the y axis only in android?
body: <p>I'm trying to restrict drag and drop motion to only the Y-axis so that a user can only take a view and drag it up or down--not left or right.</p>
  
  <p>I've got two views (ids of textView and dropZone) right now.  One (textView) has a touch listener set to it and another (dropZone) has a drag listener set on it.</p>
  
  <p>Here's the layout xml (activity_main.xml):</p>
  
  <pre><code>&lt;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" &gt;
  
  &lt;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" /&gt;
  
  &lt;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" /&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>The following is the activity code:</p>
  
  <pre><code>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;
      }
  
  }
  </code></pre>
  
  <p>As you can see from the code above, when a user drags textView over dropZone, I try to turn the dropZone view background color to blue.  This works fine if I use create a DragShadowBuilder in the ACTION_DOWN motion event:</p>
  
  <pre><code>    ClipData data = ClipData.newPlainText("", "");
      DragShadowBuilder shadow = new View.DragShadowBuilder(v);
      v.startDrag(data, shadow, v, 0);
  </code></pre>
  
  <p>The problem is that I can't control the shadow so that it only moves along the Y-axis (vertical) axis.  </p>
  
  <p>If I take out the DragShadowBuilder code (the three lines above), and add in code to move the dragged view in the ACTION_MOVE motion event (it's commented out above):</p>
  
  <pre><code>    cY1 = (int) event.getRawY();
      deltaCursorY = cY1 - cY0;
      v.setX(viewX0);
      v.setY(viewY0 + deltaCursorY);
  </code></pre>
  
  <p>Then I can control the textView to move only along the Y-axis.  Unfortunately, without a DragShadowBuilder, I can't get the ACTION_DRAG_ENTERED DragEvent to trigger to turn the dropZone view blue.</p>
  
  <p>If I leave both the DragShadowBuilder code and the four lines of code above, the ACTION_MOVE motion event is only triggered once for a drag; it doesn't continue to follow the drag around.</p>
  
  <p>Anybody have any ideas as to what I can do?  I've been tooling around with this for a while, but with no luck.  I even tried at one point to create a custom view that extends the Android View class, but I can't override the startDrag method because it's declared as final.  I wish I were better at this.  :(</p>