¿Cómo desencadenar el redibujo de un padre Ver cuando se vuelve a dibujar alguno de sus hijos?
Fondo
He escrito una vista personalizada de Android basada en un LinearLayout
que he llamado ReflectingLayout
. La idea es bastante simple, para hacer un efecto de reflexión debajo de cualquier niño Vistas declaradas dentro de ReflectingLayout
. p.ej..
- Cambiar el tamaño de los diseños de forma dinámica con ViewFlipper
- ¿Cómo forzar a mostrar y ocultar el teclado virtual si no hay teclado de hardware disponible?
- Encabezados ListView sin separadores de elementos de lista
- ¿Alguien implementó (o consiguió más información) en Android SyncObserver
- Android: el botón rápido presiona resultados en múltiples instancias de intención
Estoy logrando esto reemplazando dispatchDraw()
en ReflectingLayout
siguiente manera:
@Override protected void dispatchDraw(Canvas canvas) { Bitmap bitmap = Bitmap.createBitmap(...); Canvas tempCanvas = new Canvas(bitmap); // Draw child views to bitmap using tempCanvas super.dispatchDraw(tempCanvas); ... // some tranformations performed on bitmap ... // draw transformed image on to main canvas canvas.drawBitmap(bitmap, 0, 0, null); }
El problema
Si mi ReflectingLayout
contiene, digamos, un TextView
y cambio el contenido de texto de ese TextView
el efecto de reflexión no se está actualizando.
Creo que esto es porque Android sólo volverá a dibujar el propio TextView
en lugar de todas las vistas de los padres, lo que significa que mi método dispatchDraw()
no se llama.
¿Hay alguna forma sencilla de activar el redibujo de una vista de los padres en respuesta a los cambios en cualquiera de sus vistas secundarias?
En particular, ¿cómo puedo volver a dibujar ReflectingLayout
cuando se vuelven a dibujar las vistas de los niños?
Cosas que ya he considerado
-
He notado que un nuevo
View.OnLayoutChangeListener
se agregó en el nivel 11 de la API. Presumiblemente, esto podría ser usado para registrar una devolución de llamada a la vista principal y desencadenar una nuevaView.OnLayoutChangeListener
(?). En cualquier caso, necesito una solución que funcione en API Nivel 7 hacia arriba. -
Podría simplemente extender
TextView
y cualquier otra clase de View que quiera declarar dentro deReflectingLayout
para invalidar a sus padres cuando sean redibujados, pero esto es una solución torpe.
Cualquier ayuda recibida en gran medida (incluso si piensa que el enfoque general es incorrecto).
Gracias.
- Arrastrar y soltar + dibujo personalizado en Android
- Estilo oficial de la semana del despertador oficial de Android
- Jerarquía de estilo en Android - ¿cuál es el orden de importancia?
- Uso de TouchScreens para el control de juegos
- Hay un iUI para el Android
- Cómo llamar a los colores de los recursos de forma dinámica en Android?
- Ejecutar Android sin GUI (Android sin cabeza)
- Acceso a la interfaz de usuario de JavaScript en Android
¿Qué pasa con el método getParent()
en su vista? Algo como esto:
if (getParent() instanceof View) ((View) getParent()).invalidate();
Acabo de encontrar este problema. Me di cuenta de que se debió a la nueva compatibilidad de aceleración de hardware en View#setLayerType
LAYER_TYPE_SOFTWARE
La forma en que lo resolví estaba usando View#setLayerType
y utilizando LAYER_TYPE_SOFTWARE
. Con el fin de seguir apuntando API nivel 8 he utilizado la reflexión para llamar a este método en el apoyo a las plataformas Android. Esto resolvió el problema y ahora mi ViewGroup personalizado dibuja correctamente cuando los niños son invalidados.
No sé si esto resolverá su problema exactamente pero puede ayudar a otros que también están perplejos por este problema.
Código de reflexión, muy básico:
try { Method method = CustomViewGroup.class.getMethod("setLayerType", new Class[] { Integer.TYPE, Paint.class }); // 0x1 == LAYER_TYPE_SOFTWARE method.invoke(this, new Object[] { Integer.valueOf(0x1), null }); } catch(SecurityException e) { Log.e(TAG, "reflectSetLayerType", e); } catch(NoSuchMethodException e) { // don't care } catch(IllegalArgumentException e) { Log.e(TAG, "reflectSetLayerType", e); } catch(IllegalAccessException e) { Log.e(TAG, "reflectSetLayerType", e); } catch(InvocationTargetException e) { Log.e(TAG, "reflectSetLayerType", e); }
- Agregar manualmente canción a Mediastore como una pista de música
- Programe el trabajo recurrente utilizando el despachador de trabajo de firebase