2011-05-08 18 views
8

Quiero rotar una vista de imagen de 30 grados en cada clic en un botón.Android gire imageview, no puedo establecer la posición final de imageview en onAnimationEnd()

En el primer clic, puedo configurar la animación correctamente pero no puedo actualizar la posición de la imagen después de la animación. Cuando volví a hacer clic en el botón, la animación comienza desde la posición original de la vista de la imagen y no desde la posición final después de la primera animación.

Aquí está mi código:

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    turnImg = (ImageView) findViewById(R.id.imageViewturnImg); 
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.imgTurn); 
    // Getting width & height of the given image. 
    int w = bmp.getWidth(); 
    int h = bmp.getHeight(); 

    turnImg .setImageBitmap(bmp); 

    Button buttonok = (Button) findViewById(R.id.buttonok); 
    buttonok.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) { 
      turn(); 
     } 
    }); 

} 

public void turn() 
{ 
    float degrees = 30; 

    RotateAnimation anim = new RotateAnimation(0, degrees,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 
    anim.setInterpolator(new LinearInterpolator()); 
    anim.setDuration(300); 
    anim.setFillEnabled(true); 

    anim.setFillAfter(true); 

    anim.setAnimationListener(new AnimationListener() { 
     @Override 
     public void onAnimationEnd(Animation arg0) { 

     Matrix mat = turnImg.getImageMatrix(); 
      mat.postRotate(30,turnImg.getWidth()/2, turnImg.getHeight()/2); 
      turnImg.setScaleType(ScaleType.MATRIX); 
      turnImg.setImageMatrix(mat); 

     } 

     @Override 
     public void onAnimationRepeat(Animation animation) {} 
     @Override 
     public void onAnimationStart(Animation animation) {} 
    }); 


    turnImg.startAnimation(anim); 

} 

Creo que el problema venía de la manera que me actualizo la posición en el onAnimationEnd().

ps: lo siento por mi mala Inglés ...

+0

El hecho es que después de rotar la imagen real, se debe cancelar el "relleno después". Intenté añadiendo aAnimationEnd() la línea 'turnImg.clearAnimation()', pero tengo un error tremendo (al menos en el emulador), exactamente lo mismo que sucede si simplemente eliminas el relleno después. – bigstones

+0

Estaba pensando que mybe el problema es causado por setScaleType (ScaleType.MATRIX); En mi xml, la imagen vista turnImg está configurada en android: scaleType = "center" – colorado

+0

Lo que configura en el código simplemente anula lo que establece en xml, por lo que no hay conflicto. A medida que crea la animación mediante programación, puede crearla con el último ángulo que alcanzó como ángulo de inicio, con "llenar después" y sin rotación de la matriz.Sin embargo, no sé cómo se comporta con ángulos> 360 °. – bigstones

Respuesta

15

El problema es que la animación no está afectando el mismo objeto que la rotación de la matriz. Es decir, está animando la rotación del objeto ImageView, pero luego está configurando la rotación de la imagen que está dentro de ese objeto ImageView. Entonces, por ejemplo, la primera vez que lo gira, ImageView rota de 0 a 30 grados, y luego permanece en una rotación de 30 grados debido a la llamada a setFillAfter (true). A continuación, se ejecuta el controlador onAnimationEnd(), que gira la imagen interna 30 grados. Esto efectivamente salta la imagen a una rotación de 60 grados, como lo ve el usuario (30 para la Vista, 30 para el mapa de bits). Luego, la próxima vez que se ejecute la animación, se rota la vista de 0 a 30 grados, con la imagen interna aún en su rotación de 30 grados. Esto lo hace ver al usuario como si girara de 30 a 60 grados. Luego aplica otra rotación en la imagen interna cuando termina la animación, terminando con la imagen girada a 60 grados y la vista girada (nuevamente) a 30 grados, por lo que la imagen ahora gira visualmente a 90 grados.

Y así sucesivamente.

Existen diferentes maneras de manejar este problema, pero una forma simple es evitar afectar los dos objetos diferentes: simplemente trabaje con ImageView. En lugar de girar de 0 a 30 cada vez, gire desde cualquiera que sea la rotación actual a ese valor más 30 grados. Puede eliminar el controlador onAnimationEnd() porque ya no necesitará rotar la imagen dentro de la vista.

El código resultante para su vez() es mucho más simple:

public void turn() 
{ 
    RotateAnimation anim = new RotateAnimation(currentRotation, currentRotation + 30, 
      Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f); 
    currentRotation = (currentRotation + 30) % 360; 

    anim.setInterpolator(new LinearInterpolator()); 
    anim.setDuration(1000); 
    anim.setFillEnabled(true); 

    anim.setFillAfter(true); 
    turnImg.startAnimation(anim); 
} 

Este código se supone una variable de instancia de currentRotation, que se utiliza para realizar un seguimiento de los últimos grados de la vista se hizo girar a. Es un poco más complicado si permite que el usuario haga clic en la mitad de la animación, pero no es demasiado difícil.

Por cierto, esto es mucho más simple en el sistema de animación en 3.0; ahora hay una propiedad de "rotación" en Ver, y puede ejecutar una animación en esa propiedad y puede seguir su propio valor actual. Pero el enfoque anterior debería funcionar para versiones anteriores.

Cuestiones relacionadas