AnimatorSet无法工作的可绘制动画 - drawable消失

时间:2014-01-19 10:03:02

标签: android animation android-canvas

我正在尝试开发简单的棋盘游戏。该板的尺寸为9x9。球出现在球场上,当用户用球点击球场时,球开始跳跃。我以两种方式实现了动画。第一个是工作,但是在动画之后添加另一个动画并不容易(比如小拉伸或其他东西)。而第二个,似乎更好(使用AnimatorSet)是行不通的。当用户用球点击球场时,球会消失。我不明白为什么:-(。

第一个类实现了Board,它是View的孩子:

public class BoardView extends View {
  ...

  /**
   * Initializes fields of the board.
   */
  private void initializeFields() {
    this.fields = new ArrayList<Field>();

    for (int row = 0; row < BoardView.FIELDS_NUMBER; row++) {
       for (int column = 0; column < BoardView.FIELDS_NUMBER; column++) {
          this.fields.add(new Field(this, row, column));
       }
    }
  }

  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawColor(BoardView.COLOR_ACTIVITY);

    if (this.fields == null) {
       this.initializeFields();
    }

    for (int i = 0; i < this.fields.size(); i++) {
       this.fields.get(i).draw(canvas);
    }
  }

  ...
}

第二个实现字段:

public class Field {
   ...

   /**
    * Draws itself on the screen.
    *
    * @param Canvas canvas
    */
   public void draw(Canvas canvas) {
      Rect field = this.getRect();
      int round = (int)Math.floor(this.board.getFieldSize() / 4);

      this.board.getPainter().setStyle(Paint.Style.FILL);
      this.board.getPainter().setColor(Field.COLOR_DEFAULT);

      // draw field
      canvas.drawRoundRect(new RectF(field), round, round, this.board.getPainter());

      // draw selected field
      if (this.selected) {
         this.board.getPainter().setColor(Field.COLOR_SELECTED);
         canvas.drawRoundRect(new RectF(field), round, round, this.board.getPainter());
      }

      // draw ball
      if (this.ball != null) {
         Point fieldOrigin = new Point(field.left, field.top);

         if (this.selected) {
            this.ball.animate(canvas, fieldOrigin);
         } else {
            this.ball.draw(canvas, fieldOrigin);
         }
      }
   }

   ...
}

最后一个实现了球: 这是第一种完全有效的方法,但它不够灵活:

public class Ball {
   ...

   /**
    * Draws itself on the screen.
    *
    * @param Canvas canvas
    * @param Point fieldOrigin
    */
   public void draw(Canvas canvas, Point fieldOrigin) {
      // set painter
      Paint painter = this.field.getBoard().getPainter();

      painter.setStyle(Paint.Style.FILL);
      painter.setColor(Ball.COLORS[this.color]);

      // calculate parameters
      float halfSize = this.field.getBoard().getFieldSize() / 2;
      float cX = fieldOrigin.x + halfSize;
      float cY = fieldOrigin.y + halfSize + this.dy;
      float radius = 0.6f * halfSize;

      // draw circle
      canvas.drawCircle(cX, cY, radius, painter);

      // the code continues, because of the shadow and light simulation (radial gradients)
   }

   /**
    * Draws jumping animation.
    *
    * @param Canvas canvas
    * @param Point fieldOrigin
    */
   public void animate(Canvas canvas, Point fieldOrigin) {
      float currentDy = (this.dy - 0.1f);

      this.setDy((float)Math.abs(Math.sin(currentDy)) * (-0.15f * this.field.getBoard().getFieldSize()));
      this.draw(canvas, fieldOrigin);
      this.setDy(currentDy);

      try {
         Thread.sleep(Ball.ANIMATION_DELAY);
      } catch (InterruptedException e) {}

      this.field.invalidate();
   }

   ...
}

如您所见,动画是通过休眠当前线程并更改参数dy来实现的。

第二种方法是在球场上显示球,但动画不起作用,就像我在帖子开头所说的那样(点击后,球消失了):

public class BallShape {
   private Field field;
   private LayerDrawable ball;
   private int color;
   private float diameter,
              x, y;         // top left corner - THE GETTERS AND SETTERS ARE IMPLEMENTED (because of Animator)
   ...

   /**
    * Initializes the ball.
    *
    * @param Field field
    * @param int color
    */
   public BallShape(Field field, int color) {
      this.field = field;
      this.color = ((color == Ball.COLOR_RANDOM) ? Ball.randomColor() : color);

      // create ball
      float halfSize = this.field.getBoard().getFieldSize() / 2;

      this.diameter = 0.6f * field.getBoard().getFieldSize();
      float radius = this.diameter / 2;

      Rect fieldArea = field.getRect();
      this.x = fieldArea.left + halfSize - radius;
      this.y = fieldArea.top + halfSize - radius;

      // color circle
      OvalShape circleShape = new OvalShape();
      circleShape.resize(this.diameter, this.diameter);

      ShapeDrawable circle = new ShapeDrawable(circleShape);
      this.initPainter(circle.getPaint());

      // the code continues, because of the shadow and light simulation (radial gradients)

      // compound shape - ball
      ShapeDrawable[] compound = { circle };//, shadow, light };
      this.ball = new LayerDrawable(compound);
   }

   /**
    * Draws itself on the screen.
    *
    * @param Canvas canvas
    * @param Point fieldOrigin
    */
   public void draw(Canvas canvas, Point fieldOrigin) {
      canvas.save();

      canvas.translate(this.x, this.y);
      this.ball.draw(canvas);

      canvas.restore();
   }

   /**
    * Draws jumping animation.
    *
    * @param Canvas canvas
    * @param Point fieldOrigin
    */
   public void animate(Canvas canvas, Point fieldOrigin) {
      // common data
      float halfSize = this.field.getBoard().getFieldSize() / 2;
      float radius = this.diameter / 2;

      float startY = fieldOrigin.y + halfSize - radius;
      float endY = startY - halfSize + 2;

      // bounce animation
      ValueAnimator bounceAnimation = ObjectAnimator.ofFloat(this, "y", startY, endY);
      bounceAnimation.setDuration(BallShape.ANIMATION_LENGTH);
      bounceAnimation.setInterpolator(new AccelerateInterpolator());
      bounceAnimation.setRepeatCount(ValueAnimator.INFINITE);
      bounceAnimation.setRepeatMode(ValueAnimator.REVERSE);
    //bounceAnimation.start();

      // animation
      AnimatorSet bouncer = new AnimatorSet();
      bouncer.play(bounceAnimation);

      // start the animation
      bouncer.start();
   }

   ...
}

知道它为什么不起作用?我做错了什么? 非常感谢你。

1 个答案:

答案 0 :(得分:0)

我会解决两件事。

首先,您可以使用draw()方法开始动画。您应该在onClick()中启动它,或者至少将this.selected设置为false,以便不在每个draw()启动它。其次,在您的值动画师更改属性后,您需要重绘BallShape。否则什么都不会改变。例如,您可以定义setY(float Y)方法,在那里更改Y并调用invalidate()