studio - Android/kindle drag drop dropzing ocasionalmente
send text message android example (1)
¡HURRA! Me lo imaginé. Aquí está la respuesta en caso de que ayude a alguien en el futuro.
Finalmente lo reduje a solo el elemento de la lista superior (no sé cómo me lo perdí) y luego comencé a comentar las líneas hasta que no se rompió, lo que se redujo a esta línea:
view.setVisibility(View.GONE);
La forma en que se configuró mi lista para cada elemento utilizó la propiedad de diseño ABAJO en un diseño relativo (excepto el elemento superior). Una vez que eliminé el ítem superior de la vista, el ítem 2do a íntegro estaba debajo de un ítem que tenía visibilidad GONE para que no supiera qué hacer. La solución fue establecer el parámetro del siguiente elemento en la vista. Afortunadamente, configuré manualmente las ID de vista de mis botones de seguimiento (hay otras vistas que también se desplazan ... etiquetas, etc.) para que sean secuenciales. Así que mi solución fue simplemente encontrar el elemento con id + 1 y hacer que se convierta en el ítem superior al configurar ABAJO a cero como este ...
// the top item in my list is ALWAYS view id 1
if(thisViewId == 1){
ImageView nextTrackButton = (ImageView) trackList.findViewById(thisViewId+1);
LayoutParams ntLP = (LayoutParams) nextTrackButton.getLayoutParams();
ntLP.addRule(RelativeLayout.BELOW,0);
nextTrackButton.setLayoutParams(ntLP);
}
//hide view
view.setVisibility(View.GONE);
No estoy seguro de si esto es un problema del dispositivo o un problema con mi código, pero creé una lista ordenable simple arrastrable utilizando un diseño relativo y vistas de imágenes. Tengo razones muy específicas para hacerlo de esta manera y esa no es mi pregunta.
El problema que estoy teniendo ocasionalmente es que congelará totalmente mi aplicación. El artículo quedará atascado en el estado de arrastre. Si levanto mi dedo, el objeto de sombra (arrastrando) aún está en la pantalla y si toco la pantalla se moverá a ese punto. Esto continuará por alrededor de un minuto y luego recibiré un error que dice que la aplicación no responde, con la opción de matarlo o esperar. El único bit útil en el logcat es el siguiente:
12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.
Luego, cuando la aplicación se agota, obtengo esto como un error
12-09 14:59:09.782: E/ActivityManager(16415): ANR in com.appname.appname (com.appname.appname/.MainActivity)
12-09 14:59:09.782: E/ActivityManager(16415): Reason: keyDispatchingTimedOut
Busqué en Google este mensaje de error y la única información era alguien sin escucha de arrastre y otra persona que decía que el sensor táctil del dispositivo no estaba al día.
Idealmente, me encantaría solucionar este error y evitar que ocurra en primer lugar. Parece que sucede principalmente si arrastro rápidamente, pero no puedo pedirle a mis usuarios que no arrastren rápidamente ... ¿verdad?
Alternativamente, ¿hay alguna forma de que detecte que arrastrar ha congelado la aplicación e interrumpido el arrastre? ¿Como configurar un temporizador en el oyente táctil y si no hay mensajes de localización por arrastrar dentro de uno o dos segundos, interrumpa el arrastre? Las cosas del temporizador que sé cómo hacer, pero no sé cómo obligaría a detener el arrastre mientras está congelado. ¿Algunas ideas?
Aquí está el código:
preparar
//happens once when the app loads
RelativeLayout trackList = (RelativeLayout) findViewById(R.id.nsTrackList1);
trackList.setOnDragListener(new MyTrackDragListener(this));
//happens in a loop for each "track" (image view)
trackButton = new ImageView(this);
trackButton.setImageDrawable(nsPackages[trackId].banner[bannerSizeSelector]);
trackButton.setOnTouchListener(new MyTrackTouchListener());
En contacto
public class MyTrackTouchListener implements OnTouchListener {
boolean isDragging=false;
float prevX, prevY;
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getPointerCount() < 2 && !isDragging) return false;
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
isDragging=false;
prevX=0;
prevY=0;
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
if(isDragging) return true;
boolean wasFirst = (prevX == 0 || prevY == 0);
float theTotalDiff = Math.abs(prevX - motionEvent.getX()) + Math.abs(prevY - motionEvent.getY());
prevX=motionEvent.getX();
prevY=motionEvent.getY();
if(wasFirst) return true;
if(theTotalDiff <3) return true;
ClipData data = ClipData.newPlainText("", "");
DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
view.startDrag(data, shadowBuilder, view, 0);
int thisViewId = view.getId();
//hide view
view.setVisibility(View.GONE);
isDragging=true;
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
isDragging=false;
return true;
}else {
Integer thisAction = motionEvent.getAction();
Log.d("looper","Motion action: "+thisAction.toString());
return false;
}
}
}
En Drag
class MyTrackDragListener implements OnDragListener {
public static boolean isDragging=false;
private MainActivity parent;
public MyTrackDragListener(MainActivity myAct){
parent=myAct;
}
@Override
public boolean onDrag(View v, DragEvent event) {
int action = event.getAction();
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
isDragging=true;
// do nothing
return true;
case DragEvent.ACTION_DROP:
View view = (View) event.getLocalState();
parent.doDropSort(view,(int) event.getY());
return true;
case DragEvent.ACTION_DRAG_ENDED:
if(isDragging && event.getResult()==false){
View view2 = (View) event.getLocalState();
parent.doDropSort(view2,(int) event.getY(),true);
return true;
}
isDragging=false;
break;
case DragEvent.ACTION_DRAG_LOCATION:
parent.doDragHover((int) event.getY());
return true;
default:
Log.d("looper","drag other... "+String.valueOf(event.getAction()));
}
return false;
}
}
Algunas cosas que ya probé
- Eliminar completamente el oyente de arrastre
- Siempre devuelve verdadero de onDrag
- Siempre devuelve falso de onDrag
- Básicamente, cada combinación de retorno verdadero / falso en el arrastre y el tacto
- Quitar el dedo 2 y la parte Action_Move y desencadenar el arrastre en Action_down en su lugar
Mismos resultados Arrastrar y soltar funciona a la perfección aproximadamente el 70% del tiempo y de repente hace el comportamiento de congelación descrito anteriormente. Algunas veces es la primera vez que se arrastra, a veces es después de varias. Me he dado cuenta de un patrón constante, excepto posiblemente la velocidad de arrastre. Suele suceder cuando estoy arrastrando rápidamente, pero la dirección del arrastre o el lugar donde arrastro no parece importar.