Aplicando animações sucessivas ao ImageView no Android
Pergunta
Gostaria de aplicar animações sucessivas (digamos Scaleanimation) a um ImageView mostrando uma imagem de recurso. A animação é acionada por um botão. Por exemplo, eu gostaria de ampliar de forma incremental uma imagem em cada botão Clique.
Eu defini Fillafter = "true" na animação. No entanto, todas as animações começam no estado original do ImageView. Parece que o ImageView redefine seu estado e a animação é sempre a mesma, em vez de começar do estado final da animação anterior.
O que estou fazendo errado?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button button = (Button)findViewById(R.id.Button01);
button.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
animate();
}});
}
private void animate() {
ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
ScaleAnimation scale = new ScaleAnimation((float)1.0, (float)1.5, (float)1.0, (float)1.5);
scale.setFillAfter(true);
scale.setDuration(500);
imageView.startAnimation(scale);
}
Solução
Parece que o ImageView redefine seu estado e a animação é sempre a mesma, em vez de começar do estado final da animação anterior.
Precisamente! Tenho certeza de que há um uso para fillAfter="true"
, mas ainda não descobri o ponto para isso.
O que você precisa fazer é configurar um AnimationListener
em cada Animation
de relevância e fazer algo no ouvinte onAnimationEnd()
realmente persistir o estado final de sua animação. Eu não brinquei com ScaleAnimation
Portanto, não tenho muita certeza de qual seria a maneira de "persistir o estado final". Se isso fosse um AlphaAnimation
, indo de 1.0
para 0.0
, você faria o widget INVISIBLE
ou GONE
dentro onAnimationEnd()
, por exemplo.
Outras dicas
Eu tive o mesmo problema e criei o código a seguir para usar facilmente animações diferentes. Ele apenas suporta os níveis de tradução e alfa por enquanto, pois não usei o escala, mas poderia ser facilmente estendido para suportar mais recursos.
Eu redefini o rolo e a visibilidade antes de iniciar a animação, mas isso é apenas porque eu precisava de animações ligadas/desligadas.
E o booleano "Doend" está lá para evitar um transbordamento de pilha na recursão (o ScrollTo chama o ANAMATIONEND por algum motivo obscuro ...)
private void setViewPos(View view, Animation anim, long time){
// Get the transformation
Transformation trans = new Transformation();
anim.getTransformation(time, trans);
// Get the matrix values
float[] values = new float[9];
Matrix m = trans.getMatrix();
m.getValues(values);
// Get the position and apply the scroll
final float x = values[Matrix.MTRANS_X];
final float y = values[Matrix.MTRANS_Y];
view.scrollTo(-(int)x, -(int)y);
// Show/hide depending on final alpha level
if (trans.getAlpha() > 0.5){
view.setVisibility(VISIBLE);
} else {
view.setVisibility(INVISIBLE);
}
}
private void applyAnimation(final View view, final Animation anim){
view.scrollTo(0, 0);
view.setVisibility(VISIBLE);
anim.setAnimationListener(new AnimationListener(){
private boolean doEnd = true;
@Override
public void onAnimationEnd(Animation animation) {
if (doEnd){
doEnd = false;
setViewPos(view, animation, anim.getStartTime() + anim.getDuration());
}
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
view.startAnimation(anim);
}