Hack7-在Canvas上绘制动画效果

如果你在为你的组件添加动画效果,你就会发现Android 的API提供的效果非常的有线。有没有一种API可以直接在屏幕上绘制东西呢?答案是有的,Android提供了一个叫做Canvas的类就可以。


在这个Hack里面,我将会给你展示如何使用Canvas类来绘制元素,并创建一个在屏幕里面来回弹跳的小方块。效果如下图所示:


在创建这个程序之前,让我们先明确一下Canvas类到底是什么。下面是从Android官方文档中摘下来的说明:


Canvas提供了一个供你绘制图形的界面,它对你所有的draw动作进行响应。通过Canvas,你的绘制动作通过一个潜在的Bitmap进行展示。(这段不太会翻译,提供一下原文,大家自己看)

A Canvas works for you as a pretense, or interface, to the actual surface upon which your graphics will be drawn—it holds all of your “draw” calls. Via the Canvas, your drawing is performed upon an underlying Bitmap, which is placed into the window.


基于这个描述,Canvas类负责处理所有的draw操作。我们可以创建一个View,然后重写它的onDraw()方法,就可以在这个View上面图像了。

为了使一切更易于理解,我们创建了一个DrawView类,它负责绘制这个小方块,并更新小方块的位置。我们要使用Activity来呈现这个View的内容,接下来是Activity的代码:


public class MainActivity extends Activity {

  private DrawView mDrawView;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

	//获取屏幕的长度宽度
    Display display = getWindowManager().getDefaultDisplay();
    mDrawView = new DrawView(this);
	//让这个View占据屏幕的所有可用空间
    mDrawView.height = display.getHeight();
    mDrawView.width = display.getWidth();
	
    setContentView(mDrawView);
  }
}


我们使用了WindowManager来获取屏幕的高度和宽度。这些值将会限制DrawView在绘制的时候不能绘制出边界。之后,我们将DrawView设置为了Activity的contentView。这意味着DrawView将会占据所有可用的空间。我们来看看DrawView里面的代码:


public class DrawView extends View {
  private Rectangle mRectangle;
  public int width;
  public int height;

  public DrawView(Context context) {
    super(context);
	
	//这个就是小方块
    mRectangle = new Rectangle(context, this);
    mRectangle.setARGB(255, 255, 0, 0);
    mRectangle.setSpeedX(3);
    mRectangle.setSpeedY(3);
  }

  @Override
  protected void onDraw(Canvas canvas) {
	//强制显示更新视图
    invalidate();
	//变换小方块的位置
    mRectangle.move();
	//将小方块绘制到画布上
    mRectangle.onDraw(canvas);
  }

}


我们首先创建了一个正方形对象。这个小正方形同样也知道如何将自己绘制到Canvas上面,同时也包含了所有的那些确定自己合理位置的逻辑。当onDraw()方法被调用的时候,我们将会改变小方块的位置然后将它绘制到画布上。这里的invalidate()就是这个Hack的关键,这个函数的作用就是强制一个View进行绘制(即调用onDraw方法)。因此将invalidate()方法放到onDraw()方法里面就意味着每当View绘制完自己的时候就会马上调用invalidate()进行再次绘制。换个角度来看,我们其实就是在循环的调用小方块的move()方法和onDraw()方法来创建一个有趣的动画。下面贴一下小方块的代码:


public class Rectangle extends View {
  public static final int MAX_SIZE = 40;
  private static final int ALPHA = 255;
  private int mCoordX = 0;
  private int mCoordY = 0;
  private int mRealSize = 40;
  private int mSpeedX = 3;
  private int mSpeedY = 3;

  private boolean goRight = true;
  private boolean goDown = true;
  private DrawView mDrawView;

  private Paint mInnerPaint;
  private RectF mDrawRect;

  public Rectangle(Context context, DrawView drawView) {
    super(context);
    mDrawView = drawView;

    mInnerPaint = new Paint();

    mDrawRect = new RectF();

    /* Red is default */
    mInnerPaint.setARGB(ALPHA, 255, 0, 0);
    mInnerPaint.setAntiAlias(true);
  }

  public void setARGB(int a, int r, int g, int b) {
    mInnerPaint.setARGB(a, r, g, b);
  }

  public void setX(int newValue) {
    mCoordX = newValue;
  }

  public int getX() {
    return mCoordX;
  }

  public void setY(int newValue) {
    mCoordY = newValue;
  }

  public int getY() {
    return mCoordY;
  }

  public void move() {
    moveTo(mSpeedX, mSpeedY);
  }

  private void moveTo(int goX, int goY) {

    // check the borders, and set the direction if a border has reached
    if (mCoordX > (mDrawView.width - MAX_SIZE)) {
      goRight = false;
    }

    if (mCoordX < 0) {
      goRight = true;
    }

    if (mCoordY > (mDrawView.height - MAX_SIZE)) {
      goDown = false;
    }
    if (mCoordY < 0) {
      goDown = true;
    }

    // move the x and y
    if (goRight) {
      mCoordX += goX;
    } else {
      mCoordX -= goX;
    }
    if (goDown) {
      mCoordY += goY;
    } else {
      mCoordY -= goY;
    }

  }

  public int getSpeedX() {
    return mSpeedX;
  }

  public void setSpeedX(int speedX) {
    mSpeedX = speedX;
  }

  public int getmSpeedY() {
    return mSpeedY;
  }

  public void setSpeedY(int speedY) {
    mSpeedY = speedY;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    mDrawRect.set(mCoordX, mCoordY, mCoordX + mRealSize, mCoordY
        + mRealSize);
    canvas.drawRoundRect(mDrawRect, 0, 0, mInnerPaint);

  }

  public void setSize(int newSize) {
    mRealSize = newSize;
  }

  public int getSize() {
    return mRealSize;
  }
}


7.1 总结


在onDraw()方法里面调用invalidate()方法是创建动画的一种很简单的途径。如果你想制作一个小游戏,用这个小技巧就可以处理你游戏中的刷新的操作。


7.2 相关链接


http://developer.android.com/reference/android/graphics/Canvas.html
http://developer.android.com/guide/topics/graphics/2d-graphics.html



转载请注明原地址,谢谢!

http://blog.csdn.net/kost_/article/details/14045091

代码下载地址:

http://download.csdn.net/detail/u011418185/6489723


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值