Android粒子效果之雨
上篇文章裏面講到了自定義view的基礎和原理 ,在這基礎之上我們來看一下今天的內容,分爲如下的三個部分。
單個雨點的行爲
單個雨點的運動軌跡,實際上就是一條很短的直線做自由落體運動,於是我們先來模仿這樣的一個行爲。
private void init() {
sizeX = 10;
sizeY = 30;
startX = 100;
startY = 0;
stopX = startX + sizeX;
stopY = startY + sizeY;
paint = new Paint();
paint.setColor(0xffffffff);
}
@Override
protected void drawSub(Canvas canvas) {
canvas.drawLine(startX, startY, stopX, stopY, paint);
}
@Override
protected void logic() {
float opt = 0.5f;
startX += sizeX;
stopX += sizeX;
startY += sizeY;
stopY += sizeY;
if (startY > getHeight()) {
startX = 100;
startY = 0;
stopX = startX + sizeX;
stopY = startY + sizeY;
}
}
完善雨點行爲和下雨場景的構建
既然有個單個雨點,於是將單個雨點的作爲對象來進行封裝
public class RainItem {
private int width;// 屏幕的寬
private int height;// 屏幕的高
private float startX;// x方向起點位置
private float startY;// y方向起點位置
private float stopX;// x方向結束位置
private float stopY;// y方向結束位置
private float sizeX;// x方向上的角度
private float sizeY;// y方向上的角度
float opt;// 運動速率
private Random random;
private Paint paint;
public RainItem(int width, int height) {
super();
this.width = width;
this.height = height;
random = new Random();
paint = new Paint();
paint.setColor(0xffffffff);
init();
}
private void init() {
sizeX = 1 + random.nextInt(10);
sizeY = 10 + random.nextInt(30);
// 改變雨點x方向起點位置
startX = random.nextInt(width);
// 改變雨點y方向起點位置
startY = random.nextInt(height);
// 改變運動速度
opt = 0.2f + random.nextFloat();
// 角度的改變
stopX = startX + sizeX;
stopY = startY + sizeY;
}
public void draw(Canvas canvas) {
canvas.drawLine(startX, startY, stopX, stopY, paint);
}
public void move() {
startX += sizeX;
stopX += sizeX;
startY += sizeY;
stopY += sizeY;
if (startY > height) {
init();
}
}
}
從RainItem對象中可以看出這樣我們構建一個下雨的場景就非常的簡單,創建多個雨點對象,調用其每個雨點的draw()方法和move()
public class RainView extends BaseView {
private int size = 60;
private List<RainItem> mRainList;
public RainView(Context context) {
this(context, null);
}
public RainView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RainView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void drawSub(Canvas canvas) {
for (RainItem item : mRainList) {
item.draw(canvas);
}
}
@Override
protected void logic() {
for (RainItem item : mRainList) {
item.move();
}
}
@Override
protected void init() {
mRainList = new ArrayList<RainItem>();
for (int i = 0; i < size; i++) {
RainItem item = new RainItem(getWidth(), getHeight());
mRainList.add(item);
}
}
}
效果是
XML中定義控制下雨的屬性
在res/values下創建文件attrs.xml
<resources>
<declare-styleable name="RainView">
<!-- 雨點數量 -->
<attr name="rainNum" format="integer"></attr>
<!-- 雨點大小 -->
<attr name="rainSize" format="integer"></attr>
<!-- 雨點顏色 -->
<attr name="rainColor" format="integer"></attr>
</declare-styleable>
</resources>
在佈局文件中使用:
<com.yiye.rain.view.RainView
android:layout_width="match_parent"
android:layout_height="match_parent"
yiye:rainSize="10"
yiye:rainColor="0xffee0000"
yiye:rainNum="100" />
代碼中讀取屬性並作用到view上
public class RainView extends BaseView {
private int rainNum;
private int rainSize;
private int rainColor;
private List<RainItem> mRainList;
public RainView(Context context) {
this(context, null);
}
public RainView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// 讀取到自定義屬性
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.RainView);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.RainView_rainNum:
rainNum = a.getInt(attr, 50);
break;
case R.styleable.RainView_rainSize:
rainSize = a.getInt(attr, 50);
break;
case R.styleable.RainView_rainColor:
rainColor = a.getInt(attr, 0xffffffff);
break;
default:
break;
}
}
a.recycle();
}
public RainView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void drawSub(Canvas canvas) {
for (RainItem item : mRainList) {
item.draw(canvas);
}
}
@Override
protected void logic() {
for (RainItem item : mRainList) {
item.move();
}
}
@Override
protected void init() {
mRainList = new ArrayList<RainItem>();
for (int i = 0; i < rainNum; i++) {
RainItem item = new RainItem(getWidth(), getHeight(), rainSize,
rainColor);
mRainList.add(item);
}
}
}
最終的效果: