您的位置:首页 > 移动开发 > Android开发

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

2015-11-07 22:46 429 查看
今天又温习了一遍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()方法。具体代码如下:

<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>
程序的运行过程我在注释中写得很详细了,现在我主要介绍一下怎么在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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: