首页 > 代码库 > Android Canvas上的动画

Android 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     @Override103     protected void onDraw(Canvas canvas) {104         super.onDraw(canvas);105 106         mDrawRect.set(mCoordX, mCoordY, mCoordX + mRealSize, mCoordY107                 + 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     @Override19     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 }

源码下载:

  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, 25500);  
  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 int getX() {  
  39.     return mCoordX;  
  40.   }  
  41.   
  42.   public void setY(int newValue) {  
  43.     mCoordY = newValue;  
  44.   }  
  45.   
  46.   public int 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, 00, mInnerPaint);  
  109.   
  110.   }  
  111.   
  112.   public void setSize(int newSize) {  
  113.     mRealSize = newSize;  
  114.   }  
  115.   
  116.   public int getSize() {  
  117.     return mRealSize;  
  118.   }  

Android Canvas上的动画