Android / kindle drag drop congelación de vez en cuando
No estoy seguro de si se trata de un problema de dispositivo o un problema con mi código, pero he creado una simple lista clasificable arrastrando con un diseño relativo y vistas de imagen. Tengo razones muy específicas para hacerlo de esta manera y esa no es mi pregunta.
El problema que tengo es ocasionalmente congelar totalmente mi aplicación. El elemento quedará atascado en el estado de arrastrar. Si levanto mi dedo el objeto de sombra (arrastrar) está todavía en la pantalla y si toco la pantalla se moverá a ese punto. Esto continuará durante aproximadamente un minuto y luego obtendré un error diciendo que la aplicación no responde con la opción de matarla o esperar. El único bit útil en el logcat es el siguiente:
- Cómo envolver los botones de imagen en un diseño lineal horizontal?
- Agregar elementos a un diseño relativo de forma programática
- ¿Diferencia entre addOnGlobalLayoutListener y onWindowFocusChanged?
- No lleve el botón al primer plano al hacer clic
- Añadir dinámicamente una vista al diseño de la actividad
12-09 14:23:13.157: W/WindowManager(16415): Drag is in progress but there is no drag window handle.
Entonces, cuando la aplicación se agota, esto aparece 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
I googled este mensaje de error y la única información era alguien con ningún oyente de arrastre y otra persona diciendo que era el sensor de toque del dispositivo no mantenerse al día.
Idealmente, me encantaría arreglar este error y evitar que suceda en primer lugar. Parece que sucede sobre todo si arrastro rápidamente, pero no puedo pedir a mis usuarios que no arrastrar rápidamente … ¿verdad?
Alternativamente, hay una manera que podría detectar que arrastrar ha congelado la aplicación e interrumpir la resistencia. Como establecer un temporizador en el oyente de contacto y si no hay ningún mensaje de ubicación de arrastre en el interior como un segundo o dos interrumpir la resistencia? El temporizador cosas que sé cómo hacer, pero no sé cómo me obligaría a la fricción para detener 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 la fricción
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é
- Eliminación del oyente de arrastre por completo
- Siempre devuelve verdadero de onDrag
- Devuelve siempre false de onDrag
- Básicamente cada combinación de devolver true / false en arrastrar y tocar
- Extracción de la parte de 2 dedos y Action_Move y activación de Action_down
Mismos resultados. Arrastrar y soltar funciona perfectamente alrededor del 70% del tiempo y luego de repente hace el comportamiento de congelación descrito anteriormente. A veces es en la primera tracción a veces es después de varios. He notado en patrón consistente excepto posiblemente la velocidad de arrastre. Parece que sucede USUALLY cuando estoy arrastrando rápidamente, pero la dirección de la fricción o donde arrastrar a no parece importar.
- Android alinear el centro de diseño
- Expanda TextView con wrap_content hasta que la vista de vecino llegue al final del padre
- Alineación de fragmentos con RelativeLayout
- ¿Cuáles son las desventajas de RelativeLayout
- Ajustar el ancho a la mitad de la pantalla
- Diseño relativo en ScrollView
- RelativeLayout no muestra todos los botones
- ¿Cómo evitar la vista superpuesta en el diseño relativo en android?
¡HURRA! Me lo imaginé. Aquí está la respuesta en caso de que ayuda a alguien en el futuro.
Finalmente reduje a sólo el elemento de la lista superior (no sé cómo me perdí eso) y luego comencé a comentar las líneas hasta que no se rompió que se redujo a esta línea:
view.setVisibility(View.GONE);
La forma en que se configuró mi lista de cada elemento usó la propiedad de diseño ABAJO en un diseño relativo (excepto el elemento superior). Una vez que quité el artículo superior de la vista el segundo al primer artículo estaba debajo de un artículo que era la visibilidad GONE así que no sabía qué hacer. La solución fue establecer el parámetro del siguiente elemento en la vista. Afortunadamente, establezco manualmente las ID de vista de mis botones de pista (hay otras vistas que se desplazan demasiado .. etiquetas y tal) para que sean secuenciales. Así que mi solución fue simplemente encontrar el elemento con id + 1 y hacer que se convierta en el elemento superior por establecer debajo de 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);
- Falla de la aplicación android en android 4.4 debido a la negación de permisos de gps
- ¿Cómo puedo compartir una imagen con mi aplicación de Cordova / PhoneGap desde otra aplicación?