Android碰撞的小球,密集恐懼症者謹慎
今天又溫習了一遍Java的程序。正好用Android寫了一個小Demo,具體就是在手機螢幕上顯示多個運動的小球,小球碰到手機螢幕邊緣會自動彈回。大概就是下面圖中顯示的:
該本主要的結束的是自定義View封裝,View檢視繪製,通過xml檔案自定義View屬性並設定屬性,多執行緒Thread,小球碰撞彈回簡單演算法。
下面是製作這個Demo的簡單步驟:
step1:自定義一個View抽象類,它封裝了View類的基本方法,以及多執行緒的建立和操作方法。具體程式碼如下:
<span style="font-size:12px;">package com.example.constumeview; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.View; public abstract class BaseCustomeView extends View { private MyThread myThread = null; private class MyThread extends Thread{ @Override public void run() { while(true){ logicalDo(); postInvalidate(); //通知更新介面,會重新呼叫onDraw()函式 try{ sleep(80); }catch(Exception e){ e.printStackTrace(); } } } } public abstract void logicDo(); //邏輯處理方法 public abstract void drawSub(Canvas canvas); //繪畫內容程式碼 public abstract void initView(); @Override protected void onDraw(Canvas canvas) { if(myThread == null){ //第一次呼叫onDraw()方法的時候會建立一個執行緒,用來實現小球的碰撞彈回 initView();<span style="white-space:pre"> </span>//初始化View方法 myThread = new MyThread(); myThread.start(); //啟動執行緒 }else{ drawSub(canvas); //如果執行緒以建立,則呼叫繪製方法 } } public BaseCustomeView(Context context) { super(context); } public BaseCustomeView(Context context, AttributeSet attrs) { super(context, attrs); } } </span>
下面我對View的兩個構造方法View(Context context)和View(Context context,AttributeSet attrs)解釋一下。第一個View(Context context)只有一個上下文context的引數,一般在程式碼(.javawenjian)中建立View進行呼叫,比如View view = new View(this)。第二個構造方法View(Context context,AttributeSet attrs)有兩個引數,其中attrs是View的屬性集合。一般在佈局建立View物件時進行呼叫(.xml檔案)。
step2:然後重寫一個MyCustomeView類,繼承剛才定義的抽象類BaseCustomeView。並實現抽象方法initView()、logicalDo()、drawSub()方法。具體程式碼如下:程式的執行過程我在註釋中寫得很詳細了,現在我主要介紹一下怎麼在xml中自定義View的屬性。比如在上面程式中ballNumber和ballRadius屬性是同xml檔案設定的,以及我們自定義的MyCustomeView物件也是通過xml進行初始化的。下面是我的xml檔案中程式碼,只有幾行:<span style="font-size:12px;">package com.example.constumeview; import java.util.Random; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PointF; import android.util.AttributeSet; public class MyCustomeView extends BaseCustomeView { private Paint paint = new Paint(); private int ballNumber = 1; //定義小球個數,預設為1個,通過xml自定義屬性進行設定,詳細看後面 private PointF[] ballCenter = null; //儲存各個小球的圓心座標 private float ballRadius = 4.0f; //定義小球半徑,通過xml自定義設定,看後面解釋 private int viewWidth = 0; //手機螢幕寬度 private int viewHeight = 0; //手機螢幕高度 private float[] xspace; //儲存各個小球橫向運動速度,每個小球在橫向和縱向運動的速度是不同 private float[] yspace;//儲存各個小球縱向的運動速度 public MyCustomeView(Context context) {//程式碼中解析 super(context); } public MyCustomeView(Context context, AttributeSet attrs) {//佈局中解析屬性 super(context, attrs); TypedArray typeArray = context.obtainStyledAttributes(attrs,R.styleable.NumberText); ballNumber = typeArray.getInt(R.styleable.NumberText_ballNumber, 1);//獲得小球個數 ballRadius = typeArray.getFloat(R.styleable.NumberText_ballRadius, 4.0f);//獲得小球半徑 typeArray.recycle();//回收TypeArray資源 productBallCenter(); //產生各個小球的圓心位置 setBackgroundColor(Color.WHITE);//設定View背景色為白色 } @Override public void logicDo() {//小球碰撞彈回簡單演算法 for(int i=0;i<ballNumber;i++){ if((ballCenter[i].x-ballRadius)<0){ //如果小球到達螢幕左邊緣,設定<span style="font-family: Arial, Helvetica, sans-serif;">ballCenter[i].x = ballRadius;</span> xspace[i] = 0-xspace[i]; ballCenter[i].x = ballRadius; }else if((ballCenter[i].x+ballRadius)>viewWidth){//如果小球到達螢幕右邊緣 xspace[i] = 0-xspace[i]; ballCenter[i].x = viewWidth-ballRadius; } else if((ballCenter[i].y-ballRadius)<0){//如果小球達到螢幕上邊緣 yspace[i] = 0-yspace[i]; ballCenter[i].y = ballRadius; }else if((ballCenter[i].y+ballRadius)>viewHeight){//如果小球到達螢幕下邊緣 yspace[i] = 0-yspace[i]; ballCenter[i].y = viewHeight-ballRadius; } else{<span style="white-space:pre"> </span>//預設正常情況下 ballCenter[i].x = ballCenter[i].x+xspace[i]; ballCenter[i].y = ballCenter[i].y+yspace[i]; } } } @Override public void drawSub(Canvas canvas) {//以圓心座標繪製每個小球在螢幕中的位置 for(int i=0;i<ballNumber;i++){ /*Random random = new Random(); int r = random.nextInt(256); int g = random.nextInt(256); int b = random.nextInt(256); paint.setARGB(255,r, g, b);*/<span style="white-space:pre"> </span>//隨機產生小球的顏色,這裡我註釋了,用的是全黑 canvas.drawCircle(ballCenter[i].x, ballCenter[i].y, ballRadius, paint); } } public void productBallCenter(){ //隨機初始化小球的圓心和小球運動速度,只在initView中呼叫一次 ballCenter = new PointF[ballNumber]; xspace = new float[ballNumber]; yspace = new float[ballNumber]; Random random = new Random(); float xpoint = 0; float ypoint = 0; for(int i=0;i<ballNumber;i++){ xpoint = random.nextFloat()*viewWidth+ballRadius; ypoint = random.nextFloat()*viewHeight+ballRadius; ballCenter[i] = new PointF(xpoint,ypoint); xspace[i] = random.nextFloat()*ballRadius+1; yspace[i] = random.nextFloat()*ballRadius+1; } } @Override public void initView() { //初始化View方法,準備工作 viewWidth = getWidth(); viewHeight = getHeight(); productBallCenter(); } } </span>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
xmlns:yourname="http://schemas.android.com/apk/res/com.example.constumeview"
xmlns:android="http://schemas.android.com/apk/res/android">
<com.example.constumeview.MyCustomeView
android:layout_width="match_parent"
android:layout_height="match_parent"
yourname:ballNumber="500"
yourname:ballRadius="10.0"/>
</LinearLayout>
下面是具體步驟:
1.首先在自定義類中宣告你要在xml檔案設定的屬性,比如我在MyCustomeView中聲明瞭ballNumber和ballRadius屬性。
2.在values資料夾中建立一個attrs.xml檔案,在裡面宣告你要在xml檔案中使用的屬性,如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NumberText">
<attr name="ballNumber" format="integer"/>
<attr name="ballRadius" format="float"/>
</declare-styleable>
</resources>
name為屬性名,format為屬性的資料型別。
3.在主檢視佈局檔案中(我這裡是預設的activity_main.xml檔案),設定屬性的值,程式碼我已經貼在上面。
在主佈局中新增xmlns:yourname="http://schemas.android.com/apk/res/com.example.constumeview";
其中xmlns:yourname中xmlns是固定的,yourname可以自定義,不過設定屬性的時候要保持一致。後面的工具前面的http://schemas.android.com/apk/res/是不變的,後面的是你的工作空間包名。接下來就是設定屬性了。例如:yourname:ballNumber="500" yourname:ballRadius="10.0".詳細看上面的程式碼部分哦。
4.最後貼上我入口程式MainActivity.java中的程式碼,其實什麼都沒有,只是為了保持專案的完整性,讀者好參考。
package com.example.constumeview;
import android.app.Activity;
import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
到此一個滿螢幕都是碰撞小球的Demo就製作好了,密集恐懼症的人請將小球個數調少點哦。23333333