2010-11-09 4 views
3

J'essaie d'animer une image de balle entrant dans l'écran, en changeant de position dans l'écran et de sortir de l'écran. Je veux le faire sous forme de 3 animations; ball_in, ball_shift et ball_out, tout en étant capable de décider quand passer d'une animation à l'autre.Application de la transformation après l'animation d'un objet sur android

C'est le code que j'ai obtenu jusqu'à maintenant;

Main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent"> 

<ImageView android:id="@+id/ballImage" xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_alignParentRight="true" 
android:layout_margin="5px" 
android:src="@drawable/red_ball" 
/> 


</RelativeLayout> 

Activité principale

public class AnimationTest extends Activity 
{ 
    AnimationDrawable ballAnimation; 

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

     final ImageView ballImage = (ImageView) findViewById(R.id.ballImage); 

     final Animation ballOutAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_out); 

     final Animation ballShiftAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_shift); 
     ballShiftAnimation.setAnimationListener(new AnimationListener() 
     { 

      @Override 
      public void onAnimationEnd(
        Animation animation) { 

       ballImage.startAnimation(ballOutAnimation); 
      } 

      @Override 
      public void onAnimationRepeat(
        Animation animation) {} 

      @Override 
      public void onAnimationStart(
        Animation animation) {} 

     }); 

     final Animation ballInAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_in); 
     ballInAnimation.setAnimationListener(new AnimationListener() 
     { 

      @Override 
      public void onAnimationEnd(
        Animation animation) { 
       ballImage.startAnimation(ballShiftAnimation); 
      } 

      @Override 
      public void onAnimationRepeat(
        Animation animation) {} 

      @Override 
      public void onAnimationStart(
        Animation animation) {} 

     }); 

     ballImage.startAnimation(ballInAnimation); 

    } 

} 

ball_in.xml

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator"> 
<translate 
    android:fromXDelta="150" 
    android:toXDelta="0" 

    android:fromYDelta="0" 
    android:toYDelta="0" 

    android:duration="2000" 
    android:startOffset="0" 
    /> 

<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">   
    <translate 
     android:fromXDelta="0" 
     android:toXDelta="0" 

     android:fromYDelta="-150" 
     android:toYDelta="0" 

     android:duration="1500" 
     android:startOffset="500" 
     /> 

</set> 

</set> 

ball_shift.xml

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator"> 
<translate 
    android:fromXDelta="0" 
    android:toXDelta="130" 

    android:fromYDelta="0" 
    android:toYDelta="220" 

    android:duration="2000" 
    android:startOffset="0" 

    android:fillAfter="true" 
    /> 

<scale 
    android:fromXScale="1.0" 
    android:toXScale="0.623" 

    android:fromYScale="1.0" 
    android:toYScale="0.623" 

    android:duration="2000" 
    android:startOffset="0" 

    android:fillAfter="true" 
    /> 

</set> 

ball_out.xml

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">   
<scale 
    android:fromXScale="0.623" 
    android:toXScale="0.623" 

    android:fromYScale="0.623" 
    android:toYScale="0.623" 
    /> 

<translate 
    android:fromXDelta="130" 
    android:toXDelta="330" 

    android:duration="2000" 
    android:startOffset="0" 
    /> 
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">   
    <translate 
     android:fromYDelta="220" 
     android:toYDelta="370" 

     android:duration="1900" 
     android:startOffset="100" 
     /> 

</set> 

</set> 

j'avais tout d'abord dans une longue animation, mais je voulais partager les animations pour être en mesure d'arrêter et de poursuivre à un donné temps dans le code. Ce faisant, je me suis rendu compte que la position de l'image était remise à la position de départ lorsque l'animation était terminée et cela m'a bien sûr donné des résultats bizarres lors de la séparation des animations.

J'ai essayé d'utiliser fillAfter/fillBefore, ce qui est décrit comme l'application de transformations après/avant le processus d'animation, mais elles ne semblent rien faire pour l'image. Il revient toujours à la position de départ.

Toute aide ou suggestion sur la façon de procéder est appréciée. Merci.

+1

Je dois admettre que je suis impressionné par la façon dont vous avez formulé votre question. Je pense que c'est la première fois que j'ai vu quelqu'un mettre en forme et formuler sa première question aussi bien. +1 juste pour ça! –

Répondre

0

Cette solution n'est peut-être pas la plus élégante et peut ne pas fonctionner, mais cela vaut le coup d'essayer. Avant d'appeler la prochaine animation dans la méthode onAnimationEnd(), essayez de définir la nouvelle position ImageViews à la position où l'animation s'est terminée à l'aide de la méthode setFrame(). Cela pourrait ne pas fonctionner car je ne l'ai pas testé moi-même, mais essayez-le et dites-moi le résultat.

+0

Voyant que setFrame() est une méthode protégée, je ne peux pas l'appeler explicitement sur ma vue. J'ai essayé d'autres solutions de contournement, notamment la dernière réponse sur ce sujet; http://stackoverflow.com/questions/2563941/applying-successive-animations-to-imageview-in-android Cependant, il semble que son travail sur la transformation, mais recadre l'image, je ne peux toujours pas obtenir la mise à l'échelle travail. – Avilan

+0

@Avilan: putain ... tu as raison. N'a pas fait attention à ce désolé. –

3

Vous devez utiliser un AnimationSet pour concaténer l'animation par programme dans android. Il devrait ressembler à ceci

AnimationSet anim = new AnimationSet(false); 

final Animation ballInAnimation = AnimationUtils.loadAnimation(this, 
      R.anim.ball_in); 
ballInAnimation.setFillBefore(true); 

final Animation ballShiftAnimation = AnimationUtils.loadAnimation(this,R.anim.ball_shift); 
ballShiftAnimation.setStartOffset(ballInAnimation.getDuration()); 

final Animation ballOutAnimation = AnimationUtils.loadAnimation(this,R.anim.ball_out); 
ballOutAnimation.setStartOffset(ballInAnimation.getDuration()+ ballShiftAnimation.getDuration()); 

anim.addAnimation(ballInAnimation); 
anim.addAnimation(ballShiftAnimation); 
anim.addAnimation(ballOutAnimation); 
anim.setFillAfter(true); 

ballImage.startAnimation(anim); 

Cela devrait fonctionner vos données TweenAnimations définis dans le fichier XML sont correctement connectés. Notez que cela ne fonctionnera VISUEL, si vous avez besoin en vue de cliquable, vous devez utiliser ValueAnimator au lieu de l'animation

1

Hacky, mais vous pouvez obtenir la transformation finale et l'appliquer à votre ImageView. Je n'ai pas testé réellement l'application de la matrice retournée, mais le code de réflexion fonctionne bien.

@Override 
public void onAnimationEnd(Animation animation) { 
      Transformation t = new Transformation(); 
      final float interpolatedTime = animation.getInterpolator().getInterpolation(animation.getDuration()); 
      Class params[] = {Float.TYPE, Transformation.class}; 
      try { 

       Method m = mAnimationYouWantToGetFinalTransformationFrom.getClass().getDeclaredMethod("applyTransformation", params); 
       m.setAccessible(true); 
       m.invoke(mAnimationYouWantToGetFinalTransformationFrom, interpolatedTime, t); 

       // update object to this final transformation matrix 
       // For Example: mObjectMatrix = t.getMatrix(); 

       // run your next animation 
      } // Necessary Catch blocks 

Ce problème peut être évité pour les projets utilisant la version 3.0 et ultérieure. Utilisez un ValueAnimator - l'animation met à jour l'objet réel (dans ce cas, vos propriétés ballImage) au lieu d'animer une représentation de votre objet (ce que font les 'vieilles' animations Translate et Scale).

Questions connexes