La vista no se dibuja automáticamente al anular dispatchDraw

Estoy intentando reflejar un LinearLayout. Para que esto funcione, extendí LinerLayout para crear mi propio componente View.

Esto es lo que parece:

    public class FlipLayout extends LinearLayout implements Runnable {
        private boolean isMirroring = true;
        private Handler handler;

        public FlipLayout(Context context) {
            super(context);
            this.setWillNotDraw(false);
        }

        public FlipLayout(Context context, AttributeSet attr) {
            super(context, attr);
            this.setWillNotDraw(false);
            handler = new Handler();
            handler.postDelayed(this, 30);

        }

        @Override
        protected void dispatchDraw(Canvas canvas) {
            canvas.save();
            if (isMirroring) {
                canvas.rotate(180, getWidth() / 2, getHeight() / 2);
            }
            super.dispatchDraw(canvas);
            canvas.restore();
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            if (isMirroring)
                event.setLocation(getWidth() - event.getX(),
                        getHeight() - event.getY());
            return super.dispatchTouchEvent(event);
        }

        @Override
        public void run() {
            invalidate();
            handler.postDelayed(this, 30);
        }

    }

Esa clase funciona bien, pero solo al implementar la interfaz Runnable y al llamar a invalidate () cada pocos milisegundos.

Si solo giro el lienzo sin invalidar la vista, los cambios de las vistas secundarias no se dibujan. Ahora me pregunto cuál es la razón de este comportamiento y si hay una manera de hacerlo funcionar sin la implementación Runnable / Handler. Si elimino la línea canvas.rotate (...), los cambios de las vistas secundarias se dibujan correctamente (esto es, por ejemplo, una barra de progreso que se actualiza con frecuencia).

¡Espero que alguien pueda ayudar! Muchas gracias. Chris

preguntado el 10 de mayo de 11 a las 13:05

1 Respuestas

Me parece normal que cambiar una interfaz gráfica de usuario de forma dinámica no actualice la pantalla. En cualquier marco de interfaz gráfica de usuario, requieren que el programador solicite manualmente el redibujado.

Esto se debe a que si cambio 10 elementos en mi interfaz gráfica de usuario, no quiero volver a dibujar 10 veces, sino solo una vez al final. Y el marco no puede adivinar cuándo terminé de refactorizar la interfaz gráfica de usuario. Así que necesito llamar explícitamente a un método de actualización de alguna manera.

Alternativamente, puede invalidar su Gui directamente cuando haya terminado de rotar sus cosas, y no en un hilo separado.

contestado el 10 de mayo de 11 a las 18:05

Ok, veo tu punto. Pero, ¿por qué entonces la vista se dibuja correctamente (con todas las actualizaciones de la vista secundaria) sin hacer la rotación? Intenté invalidar la vista justo después de girar el lienzo. Eso también funcionó bien. Pero he leído en otro foro que no es una buena idea llamar a invalidate () desde witin dispatchDraw () porque invalite () en sí mismo hace que dispatchDraw () se ejecute, pero no estoy seguro de si eso es correcto. - Christopher Oehmig

No estoy seguro de qué estás haciendo exactamente, pero puedo decirte que hay dos tipos de cambios en una interfaz gráfica de usuario. Los cambios normales: por ejemplo, si se desplaza, la barra de desplazamiento tiene que moverse. Los cambios anormales: elimino un botón y agrego una vista de texto. Los cambios normales se reflejarán automáticamente en la pantalla, ya que es parte de la funcionalidad del marco. Mientras que los cambios anormales son funcionalidades avanzadas que decide utilizar como programador, y necesita actualizar la interfaz gráfica de usuario manualmente. Para su problema de envío, tal vez podría intentar mover el código rotativo fuera del método de envío. - Joel

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.