Arrastrar y soltar en android 3.x causa illegalStateException después de pequeño número en arrastra
Hay un problema con el mecanismo de arrastrar y soltar en android 3.x: después de hacer algunos arrastres (digamos 30 arrastra) una excepción se acumula (ver el enlace adjunto)
Https://groups.google.com/forum/#!msg/android-platform/2APvO248NNY/rKI-5dCT8XcJ (Estoy recibiendo en el registro lo mismo que adjunto a ese mensaje ..)
- Identificar el grupo al que se ha hecho clic en una lista expandibleListView
- ¿Cómo uso ResourceCursorTreeAdapter con vistas de grupo expandidas y contraídas en Android?
- Android WebView ZoomManager.onSizeChanged NullPointerException
- Cabezal / artículo pegajoso en la vista de reciclaje
- ¿Cuál es la mejor manera de apoyar métodos obsoletos que son reemplazados por otros nuevos?
El técnico android responde que es un error en la API y dice que la única manera de evitar el problema es llamar a Garbage Collector.
Lo hice. La excepción no se ha lanzado más, pero después de un tiempo (digamos más 30-40 arrastra) android deja de llamar al evento de caída de alguna razón.
Traté de "refrescar" todas las vistas mediante la liberación de todos los recursos / lienzo / dibujo caché / reciclaje de mapas de bits y volver a crearlos y no ayudó (no lanzar la excepción más – pero aún después de algunos arrastra el evento gota ' T trabajo)
Lo único que "ayuda" es cerrar la actividad y reiniciarla de nuevo.
Alguien ha resuelto este problema de alguna manera, o tiene una buena alternativa simple ??? (Además de implementar mi propia función de arrastrar y soltar ..)
Me gustaría obtener una solución que no me obligue a reiniciar o volver a crear cualquier cosa que no suponga ..
Aquí hay código de ejemplo que demuestra el error (no demuestra la parte que dije sobre el problema con el evento drop después de usar System.GC):
public class DragandDropExampleActivity extends Activity { private boolean mIsBeenDragged = false; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final ImageView imageViewToDRag = (ImageView) findViewById(R.id.image_view_to_drag); imageViewToDRag.setClickable(true); imageViewToDRag.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mIsBeenDragged = true; DragShadowBuilder shadowBuilder = new DragShadowBuilder(imageViewToDRag); imageViewToDRag.startDrag(null, shadowBuilder, imageViewToDRag, 0); } else if (event.getAction() == MotionEvent.ACTION_UP) { mIsBeenDragged = false; } return false; } }); } }
Este es el xml:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main_frame" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/image_view_to_drag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" > </ImageView>
Este es el seguimiento de la pila:
06-04 13:34:32.730: E/View(8061): java.lang.IllegalArgumentException at android.view.Surface.lockCanvasNative(Native Method) at android.view.Surface.lockCanvas(Surface.java:350) at android.view.View.startDrag(View.java:11489) at com.show.dragandrop.DragandDropExampleActivity$1.onTouch(DragandDropExampleActivity.java:32) at android.view.View.dispatchTouchEvent(View.java:4617) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1560) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1291) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java: 1862) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1286) at android.app.Activity.dispatchTouchEvent(Activity.java:2315) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1835) at android.view.View.dispatchPointerEvent(View.java:4689) at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2415) at android.view.ViewRoot.handleMessage(ViewRoot.java:2077) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:132) at android.app.ActivityThread.main(ActivityThread.java:4126) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:491) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) at dalvik.system.NativeStart.main(Native Method)
Para hacer que la excepción se acumule – simplemente arrastre la imagen a algún punto en la pantalla, y deje el dedo. Repetir exactamente 30 veces, y la excepción se lanza. Hice este ejemplo muy simple, para demostrar que la excepción lanzada sin ninguna sobrecarga causada por mi aplicación.
TIA
- OnTouchListener en vista invisible
- Android: icono del indicador de cambio y tamaño de la lista expandible utilizada para la navegación
- Cómo cambiar el color del divisor hijo de ExpanableListView por el archivo xml de diseño?
- ¿Cómo puedo obtener la altura del teclado del método de entrada actual sin mostrarlo?
- ¿Cómo comprobar si una viewStub ya está inflada?
- Android webview css margen izquierda / derecha no funciona
- Retener completamente WebView en fragmento tras rotación
- ¿Por qué onTouchEvent de SurfaceView llamado unos segundos retrasados?
Prueba esto: –
private OnTouchListener drag = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_MOVE) { setViewPosition(v, Math.round(event.getRawX()), Math.round(event.getRawY())); } return false; } }; private void setViewPosition(View v, int x, int y) { if (v != null) { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.leftMargin = (x - v.getMeasuredWidth() / 2); params.topMargin = (y - v.getMeasuredHeight() / 2); v.setLayoutParams(params); v.invalidate(); } }
Si se está reiniciando la actividad, entonces intente reiniciar la vista, eliminándola y agregándola de nuevo (puede ser una nueva instancia). También puede probar el personal regular (que por lo general no ayuda) como invalidate (), anular el onDraw () y ver por qué se llama o no se llama.
Prueba esto:
imageViewToDRag.startDrag(null, shadowBuilder, imageViewToDRag, 0); System.gc();
Funcionó para mí en Android 3.2!
De un comentario sobre la pregunta que cubre el problema que publicó en la discusión de Google Groups sobre:
Este problema se produce porque GC no realiza la recopilación de arrastra. Pero si la ventana se redibuja, GC realiza la recolección de arrastres. La ventana se volverá a dibujar después de que el teclado virtual se haya abierto o de que algunos ImageView hayan sido actualizados o algo así.
Por lo que suena como usted puede obtener el recolector de basura para recopilar los objetos de arrastrar forzando un redibujo de la View
contiene. No tengo un dispositivo 3.0 a mano, pero quizás algo como esto valdría la pena intentarlo:
} else if (event.getAction() == MotionEvent.ACTION_UP) { findViewById(R.id.main_frame).invalidate(); }
Es posible que necesite la sugerencia de recogida de basura sugerida en allí también:
} else if (event.getAction() == MotionEvent.ACTION_UP) { findViewById(R.id.main_frame).invalidate(); System.gc(); }
Pero creo que tienes razón al querer evitar que si es posible, así que sólo lo intentaría si no funciona sin él.
Además, creo que onTouch()
debería devolver true
, ya que has consumido el evento táctil.
Pasó mucho tiempo desde que hice esa pregunta. Cuando se lanzó Android ICS – este error ya no existía. Así que desde android ICS no hay realmente ninguna razón para escribir aplicaciones dirigidas a Honeycomb. De todos modos sólo el 0,3% del total de dispositivos Android que ejecutan esta versión del sistema operativo,
Así que para mí la respuesta es – ¡no usar Honeycomb! : ->
- Bluetooth 4.0 / Smart / Baja energía en el Samsung Galaxy S3
- Ant no reconstruye la aplicación de Android con `ant debug install`