title: Drag and drop, ListView and item Views that miss the ACTION_DRAG_STARTED event
body: <p>On Android, I use a <code>ListView</code> and I want to be able to reorder its items using drag and drop. I know there are different implementation of a "drag and drop listview", however I want to use the <a href="http://developer.android.com/guide/topics/ui/drag-drop.html" rel="noreferrer">Drag and Drop framework</a> coming since <strong>API level 11</strong>.</p>
  
  <p>It started very well until I wanted to scroll my <code>ListView</code> while doing a drag and drop. As it is written in the example below, for now, I check on top of which list element I am, so if its position is not between <code>ListView.getLastVisiblePosition()</code> and <code>ListView.getFirstVisiblePosition()</code> I use a <code>ListView.smoothScrollToPosition()</code> to view the other list items.</p>
  
  <p>It is a first implementation but it works quite well.</p>
  
  <p>The problem arises while scrolling: some elements do not answer to the drag and drop events - <code>DragEvent.ACTION_DRAG_ENTERED</code> and the others - when I am on top of them. It is due to the way the ListView manages its item views: it tries to recycle the item views that are not visible any more.</p>
  
  <p>It is all right and it works, but sometimes the <code>getView()</code> of the <code>ListAdapter</code> returns a new object. Since it is new, this object missed the <code>DragEvent.ACTION_DRAG_STARTED</code> so it does not answer to the other <code>DragEvent</code> events!</p>
  
  <p>Here is an example. In this case, if I start a drag and drop with a long click on a list item and if I drag it, the majority of items will have a green background if I am on top of them ; but some don't.</p>
  
  <p>Any idea about making them subscribe to the Drag and drop event mechanism even if they missed <code>DragEvent.ACTION_DRAG_STARTED</code>?</p>
  
  <pre><code>// Somewhere I have a ListView that use the MyViewAdapter
  // MyListView _myListView = ...
  // _myListView.setAdapter(new MyViewAdapter(getActivity(), ...));
  _myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
      @Override
      public boolean onItemLongClick(AdapterView&lt;?&gt; parent, View view, int position, long id) {
          DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
          view.startDrag(null, shadowBuilder, _myListView.getItemAtPosition(position), 0);
          return true;
      }
  });
  
  class MyViewAdapter extends ArrayAdapter&lt;MyElement&gt; {
  
      public MyViewAdapter(Context context, List&lt;TimedElement&gt; objects) {
          super(context, 0, objects);
      }
  
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          View myElementView = convertView;
          if (myElementView == null) {
              /* If the code is executed here while scrolling with a drag and drop,
               * the new view is not associated to the current drag and drop events */
              Log.d("app", "Object created!");
              // Create view
              // myElementView = ...
              // Prepare drag and drop
              myElementView.setOnDragListener(new MyElementDragListener());
          }
          // Associates view and position in ListAdapter, needed for drag and drop
          myElementView.setTag(R.id.item_position, position);
          // Continue to prepare view
          // ...
          return timedElementView;
      }
  
      private class MyElementDragListener implements View.OnDragListener {
          @Override
          public boolean onDrag(View v, DragEvent event) {
              final int action = event.getAction();
              switch(action) {
              case DragEvent.ACTION_DRAG_STARTED:
                  return true;
              case DragEvent.ACTION_DRAG_ENTERED:
                  v.setBackgroundColor(Color.GREEN);
                  v.invalidate();
                  return true;
              case DragEvent.ACTION_DRAG_LOCATION:
                  int targetPosition = (Integer)v.getTag(R.id.item_position);
                  if (event.getY() &lt; v.getHeight()/2 ) {
                      Log.i("app", "top "+targetPosition);        
                  }
                  else {
                      Log.i("app", "bottom "+targetPosition);
                  }
                  // To scroll in ListView while doing drag and drop
                  if (targetPosition &gt; _myListView.getLastVisiblePosition()-2) {
                      _myListView.smoothScrollToPosition(targetPosition+2);
                  }
                  else if (targetPosition &lt; _myListView.getFirstVisiblePosition()+2) {
                      _myListView.smoothScrollToPosition(targetPosition-2);
                  }
                  return true;
              case DragEvent.ACTION_DRAG_EXITED:
                  v.setBackgroundColor(Color.BLUE);
                  v.invalidate();
                  return true;
              case DragEvent.ACTION_DROP:
              case DragEvent.ACTION_DRAG_ENDED:
              default:
                 break;
              }
              return false;
          }       
      }
  }
  </code></pre>