Android Drag and Drop ACTION_DRAG_ENDED pas de tir

J'ai vraiment du temps à figurer ce sujet et je ne peux pas trouver d'amis avec l'expérience pertinente jusqu'à présent. C'est ma TRÈS DERNIÈRE FONCTION avant que je relâche ma TRÈS PREMIÈRE ENREGISTREMENT, ce qui me rend fou d'avoir été bloqué avec la fin en vue!

Mon glisser-déposer fonctionne parfaitement si je dépose l'objet dans une zone acceptable. Cependant, si je suis tombé ailleurs, je n'obtiens pas un événement et je ne peux pas le nettoyer après l'opération de chute de glissement échouée. J'ai besoin de l'événement ACTION_DRAG_ENDED pour déclencher. Cependant, cela ne se déclenche que (selon la documentation) si je réponde à ACTION_DRAG_STARTED avec une valeur vraie (ce qui signifie qu'il peut accepter l'objet). Le problème est ACTION_DRAG_STARTED ne se lance pas!

  • Comment configurer plusieurs auditeurs pour un événement?
  • Android: Appcompat 21 comment ajouter des ombres sur la barre d'action
  • GetLoaderManager dans ListActivity
  • Comment personnaliser DrawerItem à l'aide de lib mikepenz / MaterialDrawer
  • Application dans une application
  • Comment compiler stock android pour votre téléphone
  • Je crois donc que le point crucial est que je ne reçois pas ACTION_DRAG_STARTED. Je pose ce qui devrait être tout le code Dragdrop pertinent (ou au moins presque tous) ici:

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

    Informations étendues: DragView est une disposition d'élément dans une liste (spécifiquement une liste extensible). La vue qui accepte l'événement tactile est un petit glyphe sur la vue avec une petite poignée. Voici une capture d'écran avec une opération de traînée en cours (a pris un travail de doigts pour obtenir ce lol):

    Écran de glisser-déposer

    Donc, si je devais laisser tomber l'objet traîné sur un autre élément (ce qui les réorganise), ça fonctionne très bien. Si je le dépose ailleurs, aucun événement ne se déclenche afin que je ne puisse jamais le nettoyer. Ainsi, par exemple, dans la partie supérieure de l'écran ou si la liste est courte dans une zone vide ou la barre bleue en bas ou dans l'une des zones du système.

    Je pourrais encore résoudre ce problème en déterminant un moyen d'éviter de traîner loin d'une zone valide, donc si vous savez comment faire cela, c'est une autre façon de le résoudre. Ma dernière option serait de mettre en œuvre un événement pour toutes les vues possibles sur l'écran (encore une fois, les mises en page des listes, sur une liste, qui est sur un fragment, qui pourrait être sur diverses activités), donc évidemment cela ne serait pas souhaitable. Et en fait, si je le fais, je peux encore avoir un problème s'il est laissé tomber dans une zone UI du système (comme la barre système ou la zone des boutons capacitifs) mais je n'en suis pas sûr.

    Dans le cas où il est utile, c'est ici que j'attribue les procédures d'événement pertinentes (j'ai supprimé des lignes non pertinentes) dans les cartes d'affichage de liste.

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

    Enfin, FWIW, c'est le XML de mise en page pour la vue d'élément de liste:

     <?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> 

    Merci beaucoup pour toute aide!

  • Comment utiliser les paramètres avec HttpPost
  • Android: Comment puis-je obtenir l'activité de premier plan en cours (à partir d'un service)?
  • Désactiver l'animation par défaut de Portrait vers Paysage
  • Comment envoyer et recevoir des messages SMS de données
  • Remplacement d'une couleur dans un bitmap
  • Comment rendre EditText plus petit que par défaut?
  • 2 Solutions collect form web for “Android Drag and Drop ACTION_DRAG_ENDED pas de tir”

    Les vues qui doivent être notifiées sur les événements de glisser doivent s'inscrire OnDragListeners . Si elles doivent être conscientes lorsque des choses ou des types de choses spécifiques se déplacent, par exemple pour changer leur apparence (soit à un "DRAG ME HERE!" Ou un "DO NOT DOWN DROP AND ON"!). Même si votre vue n'est pas un endroit valide pour supprimer l'objet en cours de trajectoire, s'il doit être «désactiver le contexte», il enregistre un OnDragListener et renvoie true pour ACTION_DRAG_STARTED .

    La seule chose que je manque de votre question très approfondie, c'est exactement ce qu'il faut nettoyer? Si vous avez juste besoin de faire des choses génériques qui sont dans la portée de l'activité, vous pourriez envisager d'ajouter un OnDragListener différent à la base RelativeLayout qui s'inscrit pour les événements, mais attend ACTION_DRAG_ENDED pour alerter l'activité d'exécuter votre code de nettoyage générique

    Cela peut être lié à ce problème:

    https://code.google.com/p/android/issues/detail?id=25073

    La suppression de la fonction dispatchDragEvent comme suggéré dans ce lien a fonctionné pour moi:

     @Override public boolean dispatchDragEvent(DragEvent ev){ boolean r = super.dispatchDragEvent(ev); if (r && (ev.getAction() == DragEvent.ACTION_DRAG_STARTED || ev.getAction() == DragEvent.ACTION_DRAG_ENDED)){ // If we got a start or end and the return value is true, our // onDragEvent wasn't called by ViewGroup.dispatchDragEvent // So we do it here. onDragEvent(ev); } return r; } 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.