HackSeven Canvas上的动画
当自定义View的时候,可以利用Canvas给View添加一些动画效果。
下面的例子,是在屏幕上绘制一个红色的小方块,这个小方块会在屏幕上面“乱跳”。
知识点
使用到的知识点:
(1) 在View的子类的draw()中调用invalidate(),可以让View对象一直保持重绘状态,从而可以使Canvas一直处于绘画过程中。
(2) Canvas的绘制功能,例如绘制Rect、Circle、Path等。
(3) 小方块碰撞屏幕边缘的算法。
实现
小方块视图。
继承View类,重写onDraw()方法,并提供一些setter和getter方法,用于设置小方块的属性。判断碰撞事件的逻辑在moveTo()方法中。代码如下:
1 public class Rectangle extends View { 2 public static final int MAX_SIZE = 40; 3 private static final int ALPHA = 255; 4 private int mCoordX = 0; 5 private int mCoordY = 0; 6 private int mRealSize = 40; 7 private int mSpeedX = 3; 8 private int mSpeedY = 3; 9 10 private boolean goRight = true; 11 private boolean goDown = true; 12 private DrawView mDrawView; 13 14 private Paint mInnerPaint; 15 private RectF mDrawRect; 16 17 public Rectangle(Context context, DrawView drawView) { 18 super(context); 19 mDrawView = drawView; 20 21 mInnerPaint = new Paint(); 22 23 mDrawRect = new RectF(); 24 25 /* Red is default */ 26 mInnerPaint.setARGB(ALPHA, 255, 0, 0); 27 mInnerPaint.setAntiAlias(true); 28 } 29 30 public void setARGB(int a, int r, int g, int b) { 31 mInnerPaint.setARGB(a, r, g, b); 32 } 33 34 public void setX(int newValue) { 35 mCoordX = newValue; 36 } 37 38 public float getX() { 39 return mCoordX; 40 } 41 42 public void setY(int newValue) { 43 mCoordY = newValue; 44 } 45 46 public float getY() { 47 return mCoordY; 48 } 49 50 public void move() { 51 moveTo(mSpeedX, mSpeedY); 52 } 53 54 private void moveTo(int goX, int goY) { 55 56 // check the borders, and set the direction if a border has reached 57 if (mCoordX > (mDrawView.width - MAX_SIZE)) { 58 goRight = false; 59 } 60 61 if (mCoordX < 0) { 62 goRight = true; 63 } 64 65 if (mCoordY > (mDrawView.height - MAX_SIZE)) { 66 goDown = false; 67 } 68 if (mCoordY < 0) { 69 goDown = true; 70 } 71 72 // move the x and y 73 if (goRight) { 74 mCoordX += goX; 75 } else { 76 mCoordX -= goX; 77 } 78 if (goDown) { 79 mCoordY += goY; 80 } else { 81 mCoordY -= goY; 82 } 83 84 } 85 86 public int getSpeedX() { 87 return mSpeedX; 88 } 89 90 public void setSpeedX(int speedX) { 91 mSpeedX = speedX; 92 } 93 94 public int getmSpeedY() { 95 return mSpeedY; 96 } 97 98 public void setSpeedY(int speedY) { 99 mSpeedY = speedY; 100 } 101 102 @Override 103 protected void onDraw(Canvas canvas) { 104 super.onDraw(canvas); 105 106 mDrawRect.set(mCoordX, mCoordY, mCoordX + mRealSize, mCoordY 107 + mRealSize); 108 canvas.drawRoundRect(mDrawRect, 0, 0, mInnerPaint); 109 110 } 111 112 public void setSize(int newSize) { 113 mRealSize = newSize; 114 } 115 116 public int getSize() { 117 return mRealSize; 118 } 119 }
外层视图。
小方块是一个独立的视图,这里不直接把小方块显示在Actiity中,在它的外面又“包”了一层。代码如下:
1 public class DrawView extends View { 2 private Rectangle mRectangle; 3 4 public int width; 5 6 public int height; 7 8 public DrawView(Context context) { 9 super(context); 10 mRectangle = new Rectangle(context, this); 11 mRectangle.setARGB(255, 255, 0, 0); 12 mRectangle.setSpeedX(3); 13 mRectangle.setSpeedY(3); 14 15 } 16 17 @SuppressLint("WrongCall") 18 @Override 19 protected void onDraw(Canvas canvas) { 20 super.onDraw(canvas); 21 invalidate(); 22 23 mRectangle.move(); 24 mRectangle.onDraw(canvas); 25 26 } 27 28 }
主界面。
获取屏幕的尺寸,并把相应的尺寸赋值给DrawView对象。最后,显示DrawView对象。代码如下:
1 public class MainActivity extends Activity { 2 3 private DrawView mDrawView; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 9 Display display = getWindowManager().getDefaultDisplay(); 10 mDrawView = new DrawView(this); 11 mDrawView.height = display.getHeight(); 12 mDrawView.width = display.getWidth(); 13 setContentView(mDrawView); 14 } 15 16 }