¿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:

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?

¿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.

  • Recuperar mediante programación los datos de uso de la red de etiquetas en Android
  • Formato de audio apropiado para efectos de sonido en teléfonos Android con respecto a la eficiencia
  • Perfomance de red móvil: ¿Cuál sería el tipo de datos más eficiente para transferir datos de un servidor web a un teléfono móvil?
  • Mover instancias de Set a otro en Scala
  • Reserva de almacenamiento interno del dispositivo Android para futuros registros críticos de aplicaciones
  • Android - GC_FOR_ALLOC liberado 6346K, 7% gratis, pausado 143ms, total 143ms
  • Problema de velocidad de Android con la deserialización mediante SimpleXML
  • Desempeño de Android: "Evita los internos y los setters"
  • Inicialización perezosa de los kits de tela?
  • Está llamando libgdx SpriteBatch método de inicio y fin varias veces caro?
  • ¿Por qué Android prefiere las clases estáticas?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.