SurfaceView parpadea en negro en la carga

Tengo una aplicación de dibujo que tarda entre 2 y 5 segundos en cargar el dibujo para dibujos complicados (realizado a través de AsyncTask ). Para una mejor experiencia de usuario, durante este tiempo visualizo la versión PNG almacenada del dibujo que tengo desde el directorio de la aplicación como un ImageView , y muestro una carga de ProgressBar llamando a setContentView() en el constructor Activity:

        

Cuando se completa la AsyncTask , vuelvo a llamar a setContentView() con el nuevo diseño:

     

Cuando estaba usando un modelo Canvas simple, esto funcionó perfectamente, ya que la View DrawingCanvas personalizada dibujaba el dibujo en la pantalla en el onDraw() inicial antes de mostrarse al usuario, pero ahora usando el SurfaceView con un ciclo de dibujo, soy viendo el diseño flasheado, luego cuando se carga el dibujo, una pantalla negra durante aproximadamente un segundo, y finalmente el nuevo DrawingCanvas.

Supongo que el motivo está relacionado con el tiempo de inicio del subproceso de bucle de dibujo, y dejé mi parte superior de onDraw() en SurfaceView , y se llama, pero el canvas disponible en onDraw() no parecen dibujar a SurfaceView . También intenté establecer un fondo de color sólido en el XML de arriba, esperando como mínimo mostrar un fondo blanco, pero parece que nunca afecta, incluso configurándolo desde el código.

¿Algún consejo o una explicación de lo que estoy viendo con la pantalla en negro?

EDITAR:

Ok, he confirmado que onDraw () está dibujando en el mismo canvas, así que dejé mis operaciones de dibujo allí esperando también que en la presentación inicial de SurfaceView, el usuario vea esos dibujos como en la implementación regular de Canvas, y cuando el el hilo de dibujo se había formado, sobrescribiría el canvas.

Sin embargo, si borro las operaciones del hilo de dibujo, sí veo los resultados de onDraw (), pero de nuevo, DESPUÉS de que la pantalla en negro parpadee. Y si elimino por completo la anulación de onDraw (), sigo viendo el destello negro y luego veo el diseño con el fondo blanco del XML.

Por lo tanto, parece que no importa qué, siempre voy a ver la pantalla en negro, a menos que, en lugar de cambiar los diseños, simplemente modifique el diseño ‘flash’ existente que ya está activo.

EDIT2:

He intentado usar ViewStub para poder inflar el SurfaceView en la vista existente después de que se cargue la nota, pero el mismo issu aún se aplica. Por lo que puedo decir, hay un retraso considerable (~ 200 ms) entre el constructor de SurfaceView y la llamada a la ejecución de surfaceCreated (), pero no estoy seguro de que sea aquí donde está sucediendo la pantalla en negro, o por qué la pantalla está siendo dibujada negro…

EDIT3:

Mi bash final por ahora incluye hacer que SurfaceView sea transparente . Esto combinado con dejar el diseño existente en su lugar y simplemente agregarlo a ese diseño a través de ViewStub hubiera resultado en una solución de trabajo, pero aún así, por una fracción de segundo cuando SurfaceView se está cargando, la pantalla parpadea en negro antes de que se muestre SurfaceView, como transparente. Si alguien tiene otras ideas para probar, por favor publíquelas.

Creo que encontré el motivo del flash negro. En mi caso, estoy usando SurfaceView dentro de un Fragment y agrego dinámicamente este fragmento a la actividad después de alguna acción. En el momento en que agrego el fragmento a la actividad, la pantalla parpadea en negro. Revisé grepcode para la fuente de SurfaceView y aquí está lo que encontré: cuando la vista de superficie aparece en la ventana la primera vez, solicita el cambio de los parámetros de la ventana llamando a un IWindowSession.relayout(..) privado IWindowSession.relayout(..) . Este método “le da” un nuevo marco, ventana y superficie de ventana. Creo que la pantalla parpadea en ese momento.

La solución es bastante simple: si su ventana ya tiene los parámetros adecuados, no actualizará todas las cosas de la ventana y la pantalla no parpadeará. La solución más simple es agregar un 0px altura al primer diseño de su actividad. Esto recreará la ventana antes de que se muestre la actividad en la pantalla, y cuando configure su segundo diseño, simplemente continuará usando la ventana con los parámetros actuales. Espero que esto ayude.

ACTUALIZACIÓN : Parece que después de años este comportamiento todavía está allí. Yo recomendaría utilizar TextureView en lugar de SurfaceView. Esta es literalmente una implementación más nueva de lo mismo que no tiene este efecto secundario, así como tampoco tiene un problema de fondo negro cuando lo mueve (por ejemplo, en ScrollView, ViewPager, RecyclerView, etc.).

No haría esto con dos diseños diferentes.

Intente hacer que su elemento raíz sea RelativeLayout y luego haga que SurfaceView e ImageView sean hijos hermanos de eso. Pase lo que pase con el enhebrado, etc., ImageView debe dibujarse totalmente opaco en la parte superior del SurfaceView, por lo que no obtendrá un flash.

Una vez que su hilo de trabajo haya cargado el dibujo y SurfaceView pueda dibujarse, elimine la barra de progreso y ImageView de la jerarquía de vistas.

Supongo que está dibujando un código pesado en su vista de superficie porque, hasta donde yo sé, la vista de superficie mostrará la vista completa después de dibujar todo una vez. Le sugiero que primero vaya al método onDraw () de la vista de superficie, luego establezca el fondo del canvas y luego invoque forzosamente la invalidación para evitar esa pantalla negra. Agregue una condición para asegurarse de que esta invalidación forzada solo se invoque una vez.

Debe asegurarse de que onSurfaceChanged () no regrese hasta que haya dibujado y publicado completamente el contenido de Surface de SurfaceView.

Si utiliza NavigationDrawer con fragmentos, ¡la solución Evos no funcionará!
Intenta usar NavigationDrawer con Actividades en lugar de fragmentos, esto te ayudará al 100%

Cómo implementar NavDrawer con actividades: enlace
Otro enlace útil. (en caso de que SurfaceView dibuje encima de SlidingMenu)

“el canvas disponible en onDraw () no parece atraer a SurfaceView” – ¿Está seguro de que no crea la segunda (o tercera …) instancia de Surface View? Y algunos de ellos podrían ser negros y mostrarse por un segundo. No veo el código aquí, así que no puedo decirlo con certeza, pero si estuviera en mi aplicación, verificaría este error al principio.

Estoy enfrentando el mismo problema, pero gracias por esta respuesta

Hay un enfoque menos complicado, solo ponga getWindow (). SetFormat (PixelFormat.TRANSLUCENT); en la callback onCreate () de la actividad de host antes de llamar a setContentView ().

La solución de CrazyOrr funcionó para mí, pero fue profundo en los comentarios para la respuesta principal de Evos, así que aquí está de nuevo:

Hay un enfoque menos complicado, solo ponga getWindow (). SetFormat (PixelFormat.TRANSLUCENT); en la callback onCreate () de la actividad de host antes de llamar a setContentView (). – CrazyOrr 5 de mayo de16 a las 7:29

Simplemente poniendo

 getWindow().setFormat(PixelFormat.TRANSLUCENT); 

en la actividad onCreate() funcionó para mí.