public
class
SnowFlake {
// 雪花的角度
private
static
final
float
ANGE_RANGE =
0
.1f;
// 角度范围
private
static
final
float
HALF_ANGLE_RANGE = ANGE_RANGE / 2f;
// 一般的角度
private
static
final
float
HALF_PI = (
float
) Math.PI / 2f;
// 半PI
private
static
final
float
ANGLE_SEED = 25f;
// 角度随机种子
private
static
final
float
ANGLE_DIVISOR = 10000f;
// 角度的分母
// 雪花的移动速度
private
static
final
float
INCREMENT_LOWER = 2f;
private
static
final
float
INCREMENT_UPPER = 4f;
// 雪花的大小
private
static
final
float
FLAKE_SIZE_LOWER = 7f;
private
static
final
float
FLAKE_SIZE_UPPER = 20f;
private
final
RandomGenerator mRandom;
// 随机控制器
private
final
Point mPosition;
// 雪花位置
private
float
mAngle;
// 角度
private
final
float
mIncrement;
// 雪花的速度
private
final
float
mFlakeSize;
// 雪花的大小
private
final
Paint mPaint;
// 画笔
private
SnowFlake(RandomGenerator random, Point position,
float
angle,
float
increment,
float
flakeSize, Paint paint) {
mRandom = random;
mPosition = position;
mIncrement = increment;
mFlakeSize = flakeSize;
mPaint = paint;
mAngle = angle;
}
public
static
SnowFlake create(
int
width,
int
height, Paint paint) {
RandomGenerator random =
new
RandomGenerator();
int
x = random.getRandom(width);
int
y = random.getRandom(height);
Point position =
new
Point(x, y);
float
angle = random.getRandom(ANGLE_SEED) / ANGLE_SEED * ANGE_RANGE + HALF_PI - HALF_ANGLE_RANGE;
float
increment = random.getRandom(INCREMENT_LOWER, INCREMENT_UPPER);
float
flakeSize = random.getRandom(FLAKE_SIZE_LOWER, FLAKE_SIZE_UPPER);
return
new
SnowFlake(random, position, angle, increment, flakeSize, paint);
}
// 绘制雪花
public
void
draw(Canvas canvas) {
int
width = canvas.getWidth();
int
height = canvas.getHeight();
move(width, height);
canvas.drawCircle(mPosition.x, mPosition.y, mFlakeSize, mPaint);
}
// 移动雪花
private
void
move(
int
width,
int
height) {
double
x = mPosition.x + (mIncrement * Math.cos(mAngle));
double
y = mPosition.y + (mIncrement * Math.sin(mAngle));
mAngle += mRandom.getRandom(-ANGLE_SEED, ANGLE_SEED) / ANGLE_DIVISOR;
// 随机晃动
mPosition.set((
int
) x, (
int
) y);
// 移除屏幕, 重新开始
if
(!isInside(width, height)) {
reset(width);
}
}
// 判断是否在其中
private
boolean
isInside(
int
width,
int
height) {
int
x = mPosition.x;
int
y = mPosition.y;
return
x >= -mFlakeSize -
1
&& x + mFlakeSize <= width && y >= -mFlakeSize -
1
&& y - mFlakeSize < height;
}
// 重置雪花
private
void
reset(
int
width) {
mPosition.x = mRandom.getRandom(width);
mPosition.y = (
int
) (-mFlakeSize -
1
);
// 最上面
mAngle = mRandom.getRandom(ANGLE_SEED) / ANGLE_SEED * ANGE_RANGE + HALF_PI - HALF_ANGLE_RANGE;
}
}
public
class
RandomGenerator {
private
static
final
Random RANDOM =
new
Random();
// 区间随机
public
float
getRandom(
float
lower,
float
upper) {
float
min = Math.min(lower, upper);
float
max = Math.max(lower, upper);
return
getRandom(max - min) + min;
}
// 上界随机
public
float
getRandom(
float
upper) {
return
RANDOM.nextFloat() * upper;
}
// 上界随机
public
int
getRandom(
int
upper) {
return
RANDOM.nextInt(upper);
}
}
public
class
SnowView
extends
View {
private
static
final
int
NUM_SNOWFLAKES =
150
;
// 雪花数量
private
static
final
int
DELAY =
5
;
// 延迟
private
SnowFlake[] mSnowFlakes;
// 雪花
public
SnowView(Context context) {
super
(context);
}
public
SnowView(Context context, AttributeSet attrs) {
super
(context, attrs);
}
public
SnowView(Context context, AttributeSet attrs,
int
defStyleAttr) {
super
(context, attrs, defStyleAttr);
}
@TargetApi
(
21
)
public
SnowView(Context context, AttributeSet attrs,
int
defStyleAttr,
int
defStyleRes) {
super
(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected
void
onSizeChanged(
int
w,
int
h,
int
oldw,
int
oldh) {
super
.onSizeChanged(w, h, oldw, oldh);
if
(w != oldw || h != oldh) {
initSnow(w, h);
}
}
private
void
initSnow(
int
width,
int
height) {
Paint paint =
new
Paint(Paint.ANTI_ALIAS_FLAG);
// 抗锯齿
paint.setColor(Color.WHITE);
// 白色雪花
paint.setStyle(Paint.Style.FILL);
// 填充;
mSnowFlakes =
new
SnowFlake[NUM_SNOWFLAKES];
for
(
int
i =
0
; i < NUM_SNOWFLAKES; ++i) {
mSnowFlakes[i] = SnowFlake.create(width, height, paint);
}
}
@Override
protected
void
onDraw(Canvas canvas) {
super
.onDraw(canvas);
for
(SnowFlake s : mSnowFlakes) {
s.draw(canvas);
}
// 隔一段时间重绘一次, 动画效果
getHandler().postDelayed(runnable, DELAY);
}
// 重绘线程
private
Runnable runnable =
new
Runnable() {
@Override
public
void
run() {
invalidate();
}
};
}