本文翻译自《50 android hacks》
当自定义View的时候,可以利用Canvas给View添加一些动画效果。
下面的例子,是在屏幕上绘制一个红色的小方块,这个小方块会在屏幕上面“乱跳”。
知识点
使用到的知识点:
(1) 在View的子类的draw()中调用invalidate(),可以让View对象一直保持重绘状态,从而可以使Canvas一直处于绘画过程中。
(2) Canvas的绘制功能,例如绘制Rect、Circle、Path等。
(3) 小方块碰撞屏幕边缘的算法。
实现
小方块视图。
继承View类,重写onDraw()方法,并提供一些setter和getter方法,用于设置小方块的属性。判断碰撞事件的逻辑在moveTo()方法中。代码如下:
- 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;
- }
- }
外层视图。
小方块是一个独立的视图,这里不直接把小方块显示在Actiity中,在它的外面又“包”了一层。代码如下:
- 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);
- }
- }
主界面。
获取屏幕的尺寸,并把相应的尺寸赋值给DrawView对象。最后,显示DrawView对象。代码如下:
- 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);
- mDrawView.height = display.getHeight();
- mDrawView.width = display.getWidth();
- setContentView(mDrawView);
- }
- }
参考资料
http://developer.android.com/reference/android/graphics/Canvas.html
http://developer.android.com/guide/topics/graphics/2d-graphics.html