¿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:
- Utilizando el SDK de Android en un Mac, Eclipse es muy lento. ¿Cómo puedo acelerarlo?
- ¿Gradle escala de rendimiento bien con el número de núcleos de la CPU
- Impacto de 'instanceof' en el código Java de Android
- ¿Cómo mejorar el rendimiento de la aplicación con un mapa de Google en el construido con sencha touch y phoneGap?
- ¿Por qué usar Fragmentos?
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?
- Android, programación orientada a objetos vs diseñar para el funcionamiento
- Trazado de dibujo de Android
- FragmentPagerAdapter y FragmentStatePagerAdapter
- El objeto se convierte en nulo
- Ventaja y desventaja de CardView
- Posible BUG en Android Clase ImageDownloader: sHardBitmapCache NO estática cuando debería ser?
- Android ORMLite crear objeto lento
- Iónicos 2 problemas de rendimiento de desplazamiento
¿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)?