情境
如果想要使用一個自訂的View做如下圖的動畫,應該怎麼作?
程式碼說明
首先我們先宣告一個類別叫做MyView
public class MyView extends View {
public MyView(Context context,int screenWidth,int screenHeight){
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
}
}
讓建構子傳入Context物件,以及螢幕的長寬,
並且覆寫onDraw方法,onDraw方法只要你宣告MyView物件,
它就會執行onDraw方法把這個View重新畫一遍。
接著我們初始化一些資料
public final static int DOWN = 0;
public final static int UP = 1;
public final static int LEFT = 2;
public final static int RIGHT = 3;
private final int RANGE = 20;
private int screenWidth;//手機螢幕的寬
private int screenHeight;//手機螢幕的高
private final static int RANDOM_SPEED = 7;
private final static int BUBBLE_COUNT = 70;
private int randomSpeed;//隨機移動的pixel
private int bubbleCount;//泡泡的數量
private int direction;
public MyView(Context context,int screenWidth,int screenHeight){
super(context);
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
mBitmap = ((BitmapDrawable) this.getResources().getDrawable(
R.drawable.bubble)).getBitmap();
bubbleCount = BUBBLE_COUNT;
randomSpeed = RANDOM_SPEED;
direction = RIGHT;
bitmapX = new int[bubbleCount];
bitmapY = new int[bubbleCount];
for(int i=0;i<bubbleCount;i++){
bitmapX[i] = (int)(Math.random()*this.screenWidth+RANGE);
bitmapY[i] = (int)(Math.random()*this.screenHeight+RANGE);
}
}
首先我們定義四個方向,分別為上下左右,
然後還有隨機移動的像數,以及泡泡的數量,
隨機移動是指你想要讓畫面每畫一次,就移動幾個pixel,
泡泡的數量是指一個畫面有幾個泡泡,
以上這兩個是我隨便設定的一個值,你也可以自己定義你覺得ok的值。
mBitmap就是我們的主角泡泡了,我們從Drawable把它讀出來,
然後包裝成為Bitmap的物件。
最後我宣告兩個陣列,分別放置每個泡泡在螢幕的xy值,而且不能超過螢幕的大小。
private Bitmap bubbleSize(float size){
Matrix matrix = new Matrix();
matrix.postScale(size, size);
Bitmap resizedBitmap = Bitmap.createBitmap(mBitmap,
0, 0, mBitmap.getWidth(), mBitmap.getHeight(),matrix,true);
return resizedBitmap;
}
接著我們宣告一個方法,用來改變泡泡的大小。
private Bitmap bubbleRotation(int angle){
Matrix matrix = new Matrix();
matrix.setRotate(angle);
Bitmap RotateBitmap = Bitmap.createBitmap(mBitmap,
0, 0, mBitmap.getWidth(), mBitmap.getHeight(),matrix,true);
return RotateBitmap;
}
再來我們宣告一個方法,來改變泡泡的旋轉角度。
這裡兩個方法有一個共通點,就是利用Matrix物件來讓bitmap做大小或角度的改變。
在來自定一個方法,讓使用者設定泡泡的方向。
public void setDirection(int direction){
this.direction = direction;
}
public void decidedDirection(){
for(int i=0;i<bubbleCount;i++){
if(bitmapX[i]>=-1*RANGE && bitmapX[i] <=screenWidth+RANGE &&
bitmapY[i]>=-1*RANGE && bitmapY[i]<=screenHeight+RANGE){
switch(direction){
case DOWN:
bitmapX[i] += Math.random()*randomSpeed;
bitmapY[i] += Math.random()*randomSpeed;
break;
case UP:
bitmapX[i] += Math.random()*randomSpeed;
bitmapY[i] -= Math.random()*randomSpeed;
break;
case LEFT:
bitmapX[i] -= Math.random()*randomSpeed;
bitmapY[i] += Math.random()*randomSpeed;
break;
case RIGHT:
bitmapX[i] -= Math.random()*randomSpeed;
bitmapY[i] -= Math.random()*randomSpeed;
break;
}
}
else{
bitmapX[i] = (int)(Math.random()*screenWidth);
bitmapY[i] = (int)(Math.random()*screenHeight);
}
}
}
這個方法用來改變泡泡的方法,我們採取隨機的方式,
假設設定的方向是上的話,我們的xy就會每畫一次,就減少隨機的xy值。
同理,上下左右。
那假設超出螢幕的畫面,我們就讓它們從螢幕當中,隨機在跑出來。
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
mPaint = new Paint();
mPaint.setAntiAlias( true );
for(int i=0;i<bubbleCount;i++){
if(i%4 == 0){
int angle = (int)(Math.random()*2);
canvas.drawBitmap(bubbleRotation(angle*180),
bitmapX[i], bitmapY[i], mPaint);
}
else if(i%4 == 1){
canvas.drawBitmap(bubbleSize(SMALL),
bitmapX[i], bitmapY[i], mPaint);
}
else if(i%4 == 2){
canvas.drawBitmap(bubbleSize(BIG),
bitmapX[i], bitmapY[i], mPaint);
}
else{
canvas.drawBitmap(mBitmap, bitmapX[i], bitmapY[i], mPaint);
}
}
decidedDirection();
invalidate();
}
當所有的方法都設計好了,最重要的主角就登場了。
invalidate()方法會讓這個View一直重新呼叫onDraw(),這樣一來,
我們一直重畫一個畫面,累積起來就很像泡泡在移動,
這個方法裡面,我們設定隨機的四種可能,
而設定的條件是mod 4的值當成條件,
如果剛好是4的倍數,我就讓泡泡旋轉180度,
如果是4+1的倍數,我就讓泡泡變小,
如果是4+2的倍數,我就讓泡泡變大,
如果是4+3的倍數,我就讓泡泡呈現原始的狀態,
是不是很簡單? 你也可以設置自己的條件。
然後我們回到ViewDemoActivity的畫面來作設定,
一開始進入onCreate的時候,我們就呼叫剛剛自訂的View類別,
將其設定為我們當前的View,
private DisplayMetrics dm;
private MyView bubbleView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
bubbleView = new MyView(this,dm.widthPixels,dm.heightPixels);
setContentView(bubbleView);
}
而且我們讓目前的View跟螢幕大小是相同的。
這樣一來你就可以看到滿滿的泡泡在移動。
再來我們想要改變方向,於是我們在畫面的長按這邊加入了四個方向的選項,
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
menu.add(Menu.NONE, Menu.FIRST, Menu.NONE, "UP");
menu.add(Menu.NONE, Menu.FIRST+1, Menu.NONE, "DOWN");
menu.add(Menu.NONE, Menu.FIRST+2, Menu.NONE, "LEFT");
menu.add(Menu.NONE, Menu.FIRST+3, Menu.NONE, "RIGHT");
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch(item.getItemId()){
case Menu.FIRST:
bubbleView.setDirection(MyView.UP);
break;
case Menu.FIRST+1:
bubbleView.setDirection(MyView.DOWN);
break;
case Menu.FIRST+2:
bubbleView.setDirection(MyView.LEFT);
break;
case Menu.FIRST+3:
bubbleView.setDirection(MyView.RIGHT);
break;
}
return super.onContextItemSelected(item);
}
記得要在onCreate裡面加入這一行喔!
registerForContextMenu(bubbleView);
如此一來, 你就可以利用長按畫面,選擇上下左右了。