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

Android特效--粒子效果之雨

2015-09-02 19:07 531 查看
1. 单个雨点的行为

2. 完善雨点的行为和构造下雨场景

3. 在XML中定义可以控制下雨的属性

------------------------------------------------------

1. 单个雨点的行为: 一条线段在运动

起始点:startX , startY;

终止点:stopX, stopY;



自定义View的框架类

public abstract class BaseView extends View {

Thread thread;

public BaseView(Context context, AttributeSet attrs) {
super(context, attrs);
}

public BaseView(Context context) {
super(context);
}

@Override
final protected void onDraw(Canvas canvas) {
//禁止子类覆盖,用final
if(thread == null ) {
thread = new MyThread();
thread.start();
} else{
drawSub(canvas);
}
}

protected abstract void logic();
protected abstract void drawSub(Canvas canvas);

@Override
final protected void onDetachedFromWindow() {
// 离开屏幕时结束
//onDetachedFromWindow在销毁资源(既销毁view)之后调用
running = false;
super.onDetachedFromWindow();
}
private boolean running = true;
class MyThread extends Thread {
@Override
public void run() {
while(running) {
logic();
postInvalidate(); //线程中更新绘制,重新调用onDraw方法
try {
Thread.sleep(50); //速度太快肉眼看不到,要睡眠
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

}


自定义单个雨点RainView

public class RainView extends BaseView {

private float startX = 0;
private float startY = 0;  // Start Point
private float stopX = 0;
private float stopY = 0;  // Stop Point
private float sizeX = 0;
private float sizeY = 0;
private Paint paint;

public RainView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public RainView(Context context, AttributeSet attrs) {
super(context, attrs);
sizeX = 10;
sizeY = 30;
//单个雨点的形状,用线段表示
startX = 100;
startY = 0;
stopX = startX + sizeX;
stopY = startY + sizeY;

paint = new Paint();
paint.setColor(0xffffffff);
}

@Override
protected void logic() {
// 让雨点运动
float opt = 0.3f;
startX += sizeX * opt;
stopX += sizeX * opt;
startY += sizeY * opt;
stopY += sizeY * opt;

// 雨点出了屏幕的时候让它回到起始点
if(startY > getHeight() || startX > getWidth()){
startX = 100;
startY = 0;
stopX = startX + sizeX;
stopY = startY + sizeY;
}
}

@Override
protected void drawSub(Canvas canvas) {
// drawSub 完成绘制操作
canvas.drawLine(startX, startY, stopX, stopY, paint);
}

}


在布局文件中使用

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.carloz.raineffect.MainActivity" >

<com.carloz.raineffect.v1.single_rain.RainView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ff000000" />

</FrameLayout>


效果如下:



2. 完善雨点的行为和构造下雨场景



2.1 将雨点 效果和 行为 抽象出来

* 雨点的速度和长度是可变的

* 雨点的倾斜角度是可变的

* 雨点的位置是可变的

public class RainItem {

private int width;
private int height;

public RainItem(int width, int height) {
this.width = width;
this.height = height;
init();
}

private float startX = 0;
private float startY = 0; // Start Point
private float stopX = 0;
private float stopY = 0; // Stop Point
private float sizeX = 0;
private float sizeY = 0;
private Paint paint;
private float opt;
private Random random;

public void init() {
// TODO Auto-generated method stub
random = new Random();

sizeX = 1 + random.nextInt(10); // 随机改变雨点的角度
sizeY = 1 + random.nextInt(20);
// 单个雨点的形状,用线段表示
startX = random.nextInt(this.width);
startY = random.nextInt(this.height); // 随机改变雨点的位置
stopX = startX + sizeX;
stopY = startY + sizeY;

paint = new Paint();
paint.setColor(0xffffffff);
}

public void draw(Canvas canvas) {
canvas.drawLine(startX, startY, stopX, stopY, paint);
}

public void move() {
// 让雨点运动
opt = 0.2f + random.nextFloat(); // 随机改变雨点的速度和长度
startX += sizeX * opt;
stopX += sizeX * opt;
startY += sizeY * opt;
stopY += sizeY * opt;

// 雨点出了屏幕的时候让它回到起始点
if (startY > this.height || startX > this.width) {
startX = random.nextInt(this.width);
startY = random.nextInt(this.height);
stopX = startX + sizeX;
stopY = startY + sizeY;
}
}

}


2.2 定义多个雨点

在 添加抽象 BaseView 方法: protected abstract void init();

class MyThread extends Thread {
@Override
public void run() {
init();
while(running) {
logic();
postInvalidate(); //线程中更新绘制,重新调用onDraw方法
try {
Thread.sleep(50); //速度太快肉眼看不到,要睡眠
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}


public class RainView extends BaseView {

ArrayList<RainItem> rainList = new ArrayList<RainItem>();
int size = 80;

public RainView(Context context) {
super(context);
}

public RainView(Context context, AttributeSet attrs) {
super(context, attrs);
}

@Override
protected void init() {
// TODO Auto-generated method stub
for (int i = 0; i < size; i++) {
RainItem item = new RainItem(getWidth(), getHeight());
rainList.add(item);
}
}

@Override
protected void logic() {
for (RainItem item : rainList) {
item.move();
}
}

@Override
protected void drawSub(Canvas canvas) {
// drawSub 完成绘制操作
for (RainItem item : rainList) {
item.draw(canvas);
}
}

}


效果如下:



3. 在XML中定义可以控制下雨的属性
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: