Android碰撞的小球,密集恐惧症者谨慎

来源:互联网 发布:合肥科大讯飞待遇 知乎 编辑:程序博客网 时间:2024/04/29 03:41

今天又温习了一遍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{@Overridepublic 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();@Overrideprotected 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()方法。具体代码如下:
<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背景色为白色}@Overridepublic 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];}}}@Overridepublic 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;}}@Overridepublic void initView() {  //初始化View方法,准备工作viewWidth = getWidth();  viewHeight = getHeight();productBallCenter();}}</span>
程序的运行过程我在注释中写得很详细了,现在我主要介绍一下怎么在xml中自定义View的属性。比如在上面程序中ballNumber和ballRadius属性是同xml文件设置的,以及我们自定义的MyCustomeView对象也是通过xml进行初始化的。下面是我的xml文件中代码,只有几行:

<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





1 0
原创粉丝点击