¿Por qué llamar a setScaleX durante el gesto de pinch zoom causa parpadeo?
Estoy tratando de crear un contenedor zoomable y estoy apuntando API 14+
En mi onScale (estoy usando el ScaleGestureDetector para detectar pinch-zoom) estoy haciendo algo como esto:
- Android sólo descarga imágenes que son visibles en horizontalScrollView
- ¿Cómo ahorrar una matriz larga como números hexadecimales inversos más rápido?
- Formato de audio apropiado para efectos de sonido en teléfonos Android con respecto a la eficiencia
- El visualizador de jerarquía de Android no muestra los tiempos para la representación
- ¿Hay algún beneficio real usando el paso de peatones para Android 4.4 y superiores?
public boolean onScale (ScaleGestureDetector detector) { float scaleFactor = detector.getScaleFactor(); setScaleX(getScaleX() * scaleFactor); setScaleY(getScaleY() * scaleFactor); return true; };
Funciona, pero el zoom no es suave. De hecho, parpadea notablemente.
También lo probé con la capa de hardware pensando que la escala ocurriría en la GPU una vez que la textura se cargó y por lo tanto sería super rápido. Pero no hacía ninguna diferencia – el zoom no es suave y parpadea extrañamente a veces.
¿Qué estoy haciendo mal?
- Reserva de almacenamiento interno del dispositivo Android para futuros registros críticos de aplicaciones
- Iónicos 2 problemas de rendimiento de desplazamiento
- Android Emulator tan lento
- Descomprimir archivos de una manera más rápida que usar java.util.zip en Android
- Rendimiento de procesamiento en android
- Rendimiento JPG vs WebP en Android
- ¿Debo reemplazar las actividades de Android por fragmentos?
- Android: acelerómetro de lectura sin asignación de memoria?
¿Parece el parpadeo que la vista se mueve de un lado a otro entre zoom y no zoom? Esto es causado por tener el ScaleGestureDetector
manejando eventos de movimiento desde la misma vista que estás escalando. Cuando se setScaleX()
que cambia las coordenadas del toque, lo que desencadena un nuevo evento táctil interpretado como inversión del zoom que acaba de aplicar.
Coloque el contenido de su vista FrameLayout
dentro de un único FrameLayout
secundario y establezca la escala en esa vista.
He publicado un trabajo pinch-zoom de diseño aquí: https://gist.github.com/anorth/9845602
De acuerdo con su pregunta, los métodos setScaleX
y setScaleY
parpadean porque realizan dentro del contexto de "dibujo a una vista" ( setScaleX
y setScaleY
pertenecen a View
). La documentación dice:
Opción "a", dibujar a una vista, es su mejor opción cuando desea dibujar gráficos simples que no necesitan cambiar dinámicamente y no son parte de un juego de rendimiento intensivo. Por ejemplo, debe dibujar sus gráficos en una vista cuando desee mostrar un gráfico estático o una animación predefinida, dentro de una aplicación que de otro modo sería estática.
Por otro lado, si sigues la respuesta @ g00dy, estarás realizando dentro del contexto "dibujo a un lienzo" ( scale()
pertenece a Canvas
). La documentación dice:
La opción "b", que dibuja a un lienzo, es mejor cuando su aplicación necesita volver a dibujarse regularmente. Las aplicaciones como los videojuegos deberían estar dibujando a la lona por sí solo.
Un gesto de pellizco es intenso, por lo que debe realizarse en la opción b … por lo que debe utilizar la solución @ g00dy o cualquier enfoque como ese.
Aquí está la documentación citada.
Espero que esto te ayude.
Me enfrenté al mismo problema. La tarea fue:
- Crear lienzo (en la subclase de Vista o SurfaceView, no importa)
- Dibuje en él algunas primitivas de imagen y gráfico (con los métodos drawBitmap (), drawLine () …)
- Hacer lienzo desplazable y escalable
Supongo, no hay necesidad de mostrar todo el código de la clase aquí.
La solución del problema con el parpadeo durante el gesto de scalling fue muy simple. Sólo tiene que poner el procedimiento de escala en el método onScaleEnd () .
private class MyScaleGestureListener implements OnScaleGestureListener { public boolean onScale(ScaleGestureDetector detector) { scaleFactor *= detector.getScaleFactor(); // class variable of type float if (scaleFactor > 5) scaleFactor = 5; // some limitations if (scaleFactor < 1) scaleFactor = 1; return true; } public boolean onScaleBegin(ScaleGestureDetector detector) { return true;} public void onScaleEnd(ScaleGestureDetector detector) { setScaleX(scaleFactor); setScaleY(scaleFactor); invalidate(); // it seems to me - no effect } }
Probado en el dispositivo real Samsung GALAXY S III mini.
- Android: ¿Cómo poner un archivo de imagen de la tarjeta SD a HashMap con simpleadapter?
- ¿Cómo saber el WiFi conectado es Walled Gardened (Captive Portal)?