title: Canvas animations
body: <p>I've looked around for help on this but i can't find any answers. Currently, when i want to animate a ball, within a surfaceview, i call a method that:</p>
  
  <ol>
  <li><p>Sets an animation variable in the surfaceview to a custom class extending AnimationModule (which extends AnimationSet) which changes properties of the ball on every draw</p></li>
  <li><p>This is then called on every draw until the AnimationModule reaches its maxCount at which point it calls its inherited AnimationListener.onAnimationEnd</p></li>
  <li><p>The surfaceview receives this callback and then declares the animation variable null so that it doesn't call it on every draw any more</p></li>
  </ol>
  
  <p>This is working sort of alright at the moment but feels really bad and clunky - I'd really like to be using a tried and tested method that others use as i'm very new to animations.</p>
  
  <p>The other issue with this is that I have to use animations that extend view.animation, so ScaleAnimation, TranslateAnimation etc. It's all well and good for moving the ball around the screen, but when i come to more complicated things like animating it's perspective with canvas.polyToPoly I have to create a new class extending view.animation just for that case or make do without it.</p>
  
  <p>AnimationModule class:</p>
  
  <pre><code>public abstract class AnimationModule extends AnimationSet{
  
  protected AnimationListener listener;
  protected CreatureView attacker;
  protected CreatureView defender;
  protected BattleCanvas canvas;
  protected long increment=0;
  protected long individualIncrement=0;
  protected float interpolation=0;
  private boolean finished=false;
  private ArrayList&lt;Animation&gt; animations = new ArrayList&lt;Animation&gt;();
  private int currentAnimation=0;
  private long totalTime=0;
  
  public interface OnAnimationFinishedListener{
      public void OnAnimationFinished();
  }
  
  public AnimationModule(boolean shareInterpolator){
      super(shareInterpolator);
      init();
  }
  
  public void setCanvas(BattleCanvas canvas){
      this.canvas=canvas;
  }
  
  public void setCreatures(CreatureView attacker, CreatureView defender){
      this.attacker=attacker;
      this.defender=defender;
      Log.i("anim","attacker :"+String.valueOf(attacker.getCreature().getBaseName()));
  }
  
  public AnimationModule(boolean shareInterpolator, AnimationController controller){
      super(shareInterpolator);
  
  }
  
  private void init(){
  
      setFillAfter(true);
  
  }
  public boolean isFinished(){
      return finished;
  }
  
  @Override
  public void addAnimation(Animation a){
      Log.i("Animation","adding animation");
      animations.add(a);
      computeDuration();
      //super.addAnimation(a);
      finished=false;
  }
  
  @Override
  public void setAnimationListener(AnimationListener a){
      super.setAnimationListener(a);
      this.listener=a;
  }
  
  @Override
  public boolean getTransformation(long increment, Transformation transform){
      //super.getTransformation(increment, transform);
      if(animations.size()&gt;currentAnimation)
      animations.get(currentAnimation).getTransformation(individualIncrement, transform);
      return true;
  }
  
  public void draw(){
  
  
  }
  
  public void update(){
      if(animations.size()&gt;0){
      Log.i("Animation",String.valueOf(individualIncrement));
      Log.i("Animation",String.valueOf((animations.get(currentAnimation).getRepeatCount()+1)));
      Log.i("Animation",String.valueOf(animations.get(currentAnimation).getDuration()));
      if(individualIncrement&gt;animations.get(currentAnimation).getDuration()*(animations.get(currentAnimation).getRepeatCount()+1)){
          if(animations.size()&gt;currentAnimation+1){
              currentAnimation++;
              individualIncrement=0;
          }else{
              finished();
              return;
          }
      }
      Log.i("module","on animation "+String.valueOf(currentAnimation));
  
      increment();
      if(increment&gt;=getDuration()){
          finished();
  
      }
      }
  }
  
  
  
  protected long computeDuration(){
      long duration=0;
      Iterator&lt;Animation&gt; iterator = animations.iterator();
      while (iterator.hasNext()) {
          Animation a = iterator.next();
          duration=duration+a.computeDurationHint();
      }
      totalTime=duration;
      setDuration(duration);
      Log.i("Animation","duration set to "+String.valueOf(duration));
      return duration;
  }
  
  private void finished(){
      finished=true;
      if(listener!=null)
      listener.onAnimationEnd(this);
  }
  
  private void increment(){
      increment++;
      individualIncrement++;
      if(getDuration()!=0){
      float far = increment/getDuration();
      interpolation=far;      
      }
      else
          interpolation=0;
  }
  
  }
  </code></pre>
  
  <p>example animation extending AnimationModule:</p>
  
  <pre><code>class BiteAnimation extends AnimationModule{
  
  
      private float fromSy;
      private float fromSx;
      private ColorAnimation flash;
  
      public BiteAnimation(boolean shareInterpolator){
          super(shareInterpolator);
  
  
  
      }
  
  
      @Override
      public void setCanvas(BattleCanvas canvas){
          super.setCanvas(canvas);
  
      fromSy=defender.getSy();
  
          fromSx=defender.getSx();
  
          ScaleAnimation scale = new ScaleAnimation(fromSx,fromSx,fromSy,fromSy/2, defender.size/2, defender.size/2);
  
          scale.setDuration(50);
          scale.setRepeatMode(2);
          scale.setRepeatCount(1);
  
          addAnimation(scale);
  
           flash = new ColorAnimation(defender.getAdd(), Color.WHITE, ColorAnimation.TYPE_ADD, defender);
           flash.setDuration(50);
           flash.setRepeatMode(2);
           flash.setRepeatCount(1);
  
      }
  
      @Override
      public void update() {
          super.update();
           Transformation t = new Transformation();
  
           Log.i("Animation","increment: "+String.valueOf(individualIncrement));
                      getTransformation(individualIncrement, t);
                      defender.getMatrix().postConcat(t.getMatrix());
  
                 flash.getTransformation(individualIncrement, null);
  
  
      }
  
  }
  </code></pre>
  
  <p>as you can see, the custom animationModule just applies it's transformation to the objet it's transforming's canvas(in this case a defender). This canvas is then used when drawing the defender on the surfaceview.</p>
  
  <p>Like i said, this feels really awful and i could do with some help on how i should implement object animations.</p>