Arrastar e largar o Android ACTION_DRAG_ENDED sem disparar

Estou realmente tendo um tempo para descobrir isso e não consigo encontrar nenhum amigo com a experiência relevante até agora. É meu último recurso antes de liberar o meu PRIMEIRO APLICATIVO, então está me enlouquecendo ter ficado atolado com o fim à vista!

Meu arrastar e soltar funciona perfeitamente se eu derrubar o objeto em uma área aceitável. No entanto, se for descartado em algum outro lugar, não receberei um evento e não poderei limpá-lo após a operação de soltar com falha. Preciso do evento ACTION_DRAG_ENDED para disparar. No entanto, isso só é acionado (de acordo com a documentação) se eu responder a ACTION_DRAG_STARTED com um valor true (significando que ele pode aceitar o objeto). O problema é que ACTION_DRAG_STARTED não está disparando!

Então, acredito que o ponto crucial é que não estou recebendo ACTION_DRAG_STARTED. Eu estou colocando o que deve ser todo o código de arrastar relevante (ou pelo menos quase todos) aqui:

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>>>START DOESN"T FIRE
        case DragEvent.ACTION_DROP:
            if ((dragSource != null) && (dragSource != v)) {
                Item source = (Item) dragSource.getTag();
                Item target = (Item) v.getTag();
                int sourcePos = source.getPosition();
                int targetPos = target.getPosition();
                if (targetPos < 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;
    }

};

Informações estendidas: O dragView é um layout de item em um listview (especificamente um expandablelistview). A exibição que aceita o evento de toque é um pequeno glifo na exibição com uma pequena aderência. Aqui está uma captura de tela com uma operação de arrastar em andamento (levou alguns dedinhos para obter este lol):

Então, se eu fosse soltar o item arrastado em outro item (isso os reordena), ele funciona muito bem. Se eu derrubar em algum outro lugar, nenhum evento será disparado, então nunca poderei limpá-lo. Assim, por exemplo, na parte superior da tela ou se a lista é curta em uma área em branco ou a barra azul na parte inferior ou qualquer uma das áreas do sistema.

Eu poderia, alternativamente, resolver este problema, descobrindo uma maneira de evitar o arrastamento de uma área válida, por isso, se você sabe como fazer isso, é outra maneira de resolvê-lo. Minha última opção seria implementar um evento para todas as visualizações possíveis na tela (novamente, esses são layouts de exibição de lista, em um listview, que está em um fragmento, que poderia estar em várias atividades), então obviamente isso não seria desejável. E, de fato, se eu fizer isso, ainda posso ter um problema se ele for descartado em uma área de interface do usuário do sistema (como a área de botões capacitivos ou do sistema), mas não tenho certeza.

Caso seja útil aqui, é onde eu atribuo os procedimentos de eventos relevantes (removi linhas irrelevantes) nos adaptadores de visualização de lista que recebem o método de item de visão:

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;
}

E finalmente FWIW, este é o layout XML para a exibição de item de lista:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="55dip"
android:orientation="horizontal" >
<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"/>
<CheckBox 
    android:id="@+id/chkParent"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@id/imgGrip"
    android:checked="false"/>
<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"/>
<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" />   
<View 
    android:id="@id/viewParent"
    android:layout_height="match_parent"
    android:layout_width="0dp"
    android:layout_toLeftOf="@+id/btnExpand"/>    
<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"/>   
</RelativeLayout>

Muito obrigado por qualquer ajuda!

questionAnswers(2)

yourAnswerToTheQuestion