title: Android Drag and Drop ACTION_DRAG_ENDED not firing
body: <p>I'm really having a time figuring this one out and can't find any friends with the relevant experience so far.  It's my VERY LAST FEATURE before I release my VERY FIRST APP so it's driving me crazy to have gotten bogged down with it with the end in sight! </p>
  
  <p>My drag and drop works perfectly if I drop the object in an acceptable area.  However, if dropped somewhere else I do not get an event and cannot clean up after the failed drag drop operation.  I need the ACTION_DRAG_ENDED event to fire.  However this only fires (according to the documentation) if I respond to ACTION_DRAG_STARTED with a value of true (meaning it can accept the object).  The problem is ACTION_DRAG_STARTED is not firing!</p>
  
  <p>So I believe the crux of the matter is that I'm not getting ACTION_DRAG_STARTED.  I'm putting what should be all of the relevant dragdrop code (or at least nearly all) here:</p>
  
  <pre><code>private OnTouchListener onTouchListener = new OnTouchListener() {
  
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          if (event.getAction() == MotionEvent.ACTION_DOWN) {
              Item current = (Item) ((View) v.getTag()).getTag();
              //ClipData data = ClipData.newPlainText("test", "testText");
              View dragView = (View) v.getTag();
              DragShadowBuilder shadowBuilder = new ItemDragShadowBuilder(dragView, 
                                  new Point(v.getWidth()/2, v.getHeight()/2));
              dragSource = dragView;
              v.startDrag(null, shadowBuilder, current, 0);
              dragView.setVisibility(View.INVISIBLE);
              return true;
          } else {
              return false;
          }       
      }
  
  };
  
  private static class ItemDragShadowBuilder extends View.DragShadowBuilder {
  
      private Point touchPoint = null;
      private Point sizePoint = null;
      private View dragView = null;
  
      public ItemDragShadowBuilder(View dragView, Point touchPoint) {
          super();
          sizePoint = new Point(dragView.getWidth(), dragView.getHeight());
          this.touchPoint = touchPoint;
          this.dragView = dragView;
      }
  
      @Override
      public void onProvideShadowMetrics (Point size, Point touch) {
          size.set(sizePoint.x, sizePoint.y);
          touch.set(touchPoint.x,touchPoint.y);
      }
  
      @Override
      public void onDrawShadow(Canvas canvas) {
  
          dragView.setBackgroundColor(dragView.getContext().getResources().getColor(R.color.holoBlueDark));
          dragView.draw(canvas);
  
          //canvas.setBitmap(dragView.getDrawingCache());
          //canvas.drawColor(Color.WHITE);
          //dragView.setAlpha(1);
  
          //How do I change the transparency?
          //super.onDrawShadow(canvas);
      }
  
  
  
  }
  
  
  private View dragSource = null;
  
  private OnDragListener onDragEventListener = new OnDragListener() {
  
      @Override
      public boolean onDrag(View v, DragEvent event) {
          final int action = event.getAction();
  
          switch (action) {
          case DragEvent.ACTION_DRAG_STARTED:
              Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString() + " started", Toast.LENGTH_SHORT/8).show();
              return true;
              //break;//DRAG AND DROP&gt;&gt;&gt;START DOESN"T FIRE
          case DragEvent.ACTION_DROP:
              if ((dragSource != null) &amp;&amp; (dragSource != v)) {
                  Item source = (Item) dragSource.getTag();
                  Item target = (Item) v.getTag();
                  int sourcePos = source.getPosition();
                  int targetPos = target.getPosition();
                  if (targetPos &lt; sourcePos)
                      source.moveUp(sourcePos - targetPos);
                  else
                      source.moveDown(targetPos - sourcePos);
                  dragSource.setVisibility(View.VISIBLE);
                  dragSource = null;
                  fireOnChecklistNeedsResetListener();
                  return true;
              }
  //              View view = (View) event.getLocalState();
  //              Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
  //              Toast.makeText(v.getContext(), ((EditText) view.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
              // Dropped, reassign View to 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:
              dragSource.setVisibility(View.VISIBLE);
              dragSource = null;
              fireOnChecklistNeedsResetListener();
              if (!event.getResult())
                  Toast.makeText(v.getContext(), "UNHANDLED", Toast.LENGTH_SHORT/8).show();
  
  //              View vieww = (View) event.getLocalState();
  //              Toast.makeText(v.getContext(), ((EditText) v.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
  //              Toast.makeText(v.getContext(), ((EditText) vieww.findViewById(R.id.edtParent)).getText().toString(), Toast.LENGTH_SHORT/8).show();
              break;
          case DragEvent.ACTION_DRAG_ENTERED:
  
              v.setBackgroundColor(v.getContext().getResources().getColor(R.color.holoBlueLight));
              return true;
              //break;
          case DragEvent.ACTION_DRAG_EXITED:        
              v.setBackgroundColor(v.getContext().getResources().getColor(android.R.color.background_light));
              return false;
              //break;
          default:
              break;
      }
          return false;
      }
  
  };
  </code></pre>
  
  <p>Extended information:  The dragView is an item layout in a listview (specifically an expandablelistview).  The view that accepts the touch event is a small glyph on the view with a small grip.  Here is a screenshot with a drag operation in progress (took some fancy finger work to get this lol):</p>
  
  <p><img src="https://i.stack.imgur.com/ngQyY.png" alt="Drag/Drop Screen"></p>
  
  <p>So if I were to drop the dragged item on another item (this reorders them) it works great.  If I drop it somewhere else no event fires so I can never clean it up.  So for example in the upper part of the screen or if the list is short in a blank area or the blue bar on bottom or any of the system areas.</p>
  
  <p>I could alternatively solve this problem by figuring out a way to prevent dragging away from a valid area so if you know how to do that, that's another way to solve it.  My last option would be to implement an event for every possible view on the screen (again these are list view layouts, on a listview, which is on a fragment, which could be on various activities) so obviously this would not be desirable.  And in fact if I do that I still may have a problem if it's dropped in a system UI area (like systembar or capacitive buttons area) but I'm not sure.</p>
  
  <p>In case it is helpful here is where I assign the relevant event procedures (I removed irrelevant lines) in the list view adapters get view item method:</p>
  
  <pre><code>public View getGroupEdit(int groupPosition, boolean isExpanded, View convertView,
          ViewGroup parent) {
      if (convertView != null) {
                  //irrelevant stuff omitted
      } else
          convertView = inf.inflate(R.layout.edit_group_item, null);
      Item group = (Item) getGroup(groupPosition);
      convertView.setTag(group);
      EditText edtParent = (EditText) convertView.findViewById(R.id.edtParent);
      edtParent.setTag(convertView);
      scatterItemText(edtParent);
  
              //irrelevant stuff omitted
  
      ImageView imgGrip = (ImageView) convertView.findViewById(R.id.imgGrip);
      imgGrip.setTag(convertView);
               //irrelevant stuff omitted     
  
              imgGrip.setOnTouchListener(onTouchListener);
      convertView.setOnDragListener(onDragEventListener);
      return convertView;
  }
  </code></pre>
  
  <p>And finally FWIW, this is the layout XML for the list item view:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="55dip"
  android:orientation="horizontal" &gt;
  &lt;ImageView 
      android:id="@+id/imgGrip"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_alignParentLeft="true"
      android:src="@drawable/dark_grip2"
      android:contentDescription="@string/strReorder"/&gt;
  &lt;CheckBox 
      android:id="@+id/chkParent"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_toRightOf="@id/imgGrip"
      android:checked="false"/&gt;
  &lt;EditText
      android:id="@+id/edtParent"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_toRightOf="@id/chkParent"
      android:layout_toLeftOf="@+id/btnInsert"
      android:textSize="17dip" 
      android:inputType="text"
      android:hint="@string/strItem"/&gt;
  &lt;ImageButton
      android:id="@id/btnInsert"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      android:layout_toLeftOf="@+id/viewParent"
      android:src="@drawable/dark_content_new"
      android:clickable="true"
      android:hint="@string/strAddItemAbove"
      android:contentDescription="@string/strAddItemAbove" /&gt;   
  &lt;View 
      android:id="@id/viewParent"
      android:layout_height="match_parent"
      android:layout_width="0dp"
      android:layout_toLeftOf="@+id/btnExpand"/&gt;    
  &lt;ImageButton 
      android:id="@id/btnExpand"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      android:layout_alignParentRight="true"
      android:src="@drawable/dark_add_sub_item"
      android:clickable="true"
      android:hint="@string/strViewSubItems"
      android:contentDescription="@string/strViewSubItems"/&gt;   
  &lt;/RelativeLayout&gt;
  </code></pre>
  
  <p>Thanks so much for any help!</p>