自定义的自然飘落动画 飘落的图片自定义 自由替换,view跟之前的一样,直接复制直接用
/**
* @Description: TODO 自定义图片从左上角往左下角飘动动画
*/
public class SnowFlyView extends View {
private final int msgWhat = 0x01;
public static final long DEFAULTDURATION = 300L;
/**
* the distance of snow start falling to the view top
*/
private int initToTop;
/**
* the distance of snow start falling to the view left
*/
private int initToLeft;
/**
* the distance of snow start falling to the view bottom
*/
private int initToBottom;
/**
* the distance of snow start falling to the view right
*/
private int initToRight;
private float minScale;
private float maxScale;
private float xSpeed;
private float ySpeed;
private int snowCount;
private long snowDuration;
private List<Snow> snowList;
private BitmapDrawable snowBitmap;
private Matrix mtx = new Matrix();
private ValueAnimator animator;
private Random xRandom = new Random();
private Random yRandom = new Random();
private boolean isDelyStop;
private boolean sendMsgable;
/**
* the range of snow start falling in the x direction
*/
private float xWidth;
/**
* the range of snow start falling in the y direction
*/
private float yHeight;
private Context mContext;
private ArrayList<Drawable> imageList;
public SnowFlyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SnowFlyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
initAttr(context, attrs);
init();
}
private void initAttr(Context context, AttributeSet attrs) {
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.SnowFlyView);
int initTo = attributes.getDimensionPixelSize(R.styleable.SnowFlyView_snow_initTo, 0);
initToTop = attributes.getDimensionPixelSize(R.styleable.SnowFlyView_snow_initToTop, 0);
initToLeft = attributes.getDimensionPixelSize(R.styleable.SnowFlyView_snow_initToLeft, 0);
initToBottom = attributes.getDimensionPixelSize(R.styleable.SnowFlyView_snow_initToBottom, 0);
initToRight = attributes.getDimensionPixelSize(R.styleable.SnowFlyView_snow_initToRight, 0);
minScale = attributes.getFloat(R.styleable.SnowFlyView_snow_minScale, 1.0f);
maxScale = attributes.getFloat(R.styleable.SnowFlyView_snow_maxScale, 1.0f);
xSpeed = attributes.getFloat(R.styleable.SnowFlyView_snow_xSpeed, 0.0f);
ySpeed = attributes.getFloat(R.styleable.SnowFlyView_snow_ySpeed, 100.0f);
snowCount = attributes.getInt(R.styleable.SnowFlyView_snow_count, 20);
snowDuration = attributes.getInt(R.styleable.SnowFlyView_snow_duration, 0);
snowBitmap = (BitmapDrawable) attributes.getDrawable(R.styleable.SnowFlyView_snow_bitmap);
if (0 != initTo)
initToTop = initToLeft = initToBottom = initToRight = initTo;
if (minScale <= 0.0f || minScale > maxScale)
throw new IllegalArgumentException("The minScale is illegal");
sendMsgable = snowDuration > DEFAULTDURATION;
attributes.recycle();
}
private void init() {
/**
* close software/hardware
*/
setLayerType(View.LAYER_TYPE_NONE, null);
snowList = new ArrayList<>(snowCount);
animator = ValueAnimator.ofFloat(0.0f, 1.0f);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.setDuration(DEFAULTDURATION);
animator.addUpdateListener(new animatorUpdateListenerImp());
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
xWidth = getWidth() - initToLeft - initToRight;
yHeight = getHeight() - initToTop - initToBottom;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < snowList.size(); i++) {
Snow snow = snowList.get(i);
mtx.setTranslate(-snow.bpWidth / 2, -snow.bpHeight / 2);
mtx.postTranslate(snow.bpWidth / 2 + snow.x, snow.bpHeight / 2 + snow.y);
canvas.drawBitmap(snow.snowBitmap, mtx, null);
}
}
/**
* init snowList
*/
private void initSnows() {
if (null == snowBitmap) return;
snowList.clear();
for (int i = 0; i < snowCount; i++) {
if(imageList!= null && imageList.size()>0){
int who = (int) (Math.random() * imageList.size());
snowBitmap = (BitmapDrawable)imageList.get(who);
}
Snow snow = new Snow(xSpeed, ySpeed, snowBitmap.getBitmap());
snowList.add(snow);
}
}
public void setImageDrawableList(ArrayList<Drawable> imageList){
this.imageList = imageList;
}
/**
* stop animation dely
*/
public void stopAnimationDely() {
removeMessages();
this.isDelyStop = true;
}
/**
* stop animation and clear snowList
*/
public void stopAnimationNow() {
removeMessages();
snowList.clear();
invalidate();
animator.cancel();
}
/**
* start animation
*/
public void startAnimation() {
this.isDelyStop = false;
if (animator.isRunning())
animator.cancel();
if (sendMsgable) {
removeMessages();
handler.sendEmptyMessageDelayed(msgWhat, snowDuration);
}
initSnows();
animator.start();
}
/**
* set the duration of animation
*/
public void setSnowDuration(long snowDuration) {
this.snowDuration = snowDuration;
sendMsgable = snowDuration > DEFAULTDURATION;
}
/**
* back the state of animation
*/
public boolean isRunning() {
return animator.isRunning();
}
@Override
protected void onDetachedFromWindow() {
removeMessages();
if (animator.isRunning())
animator.cancel();
super.onDetachedFromWindow();
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == msgWhat)
isDelyStop = true;
}
};
private void removeMessages() {
if (handler.hasMessages(msgWhat))
handler.removeMessages(msgWhat);
}
private class animatorUpdateListenerImp implements ValueAnimator.AnimatorUpdateListener {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
for (int i = 0; i < snowList.size(); i++) {
Snow snow = snowList.get(i);
snow.x += snow.xSpeed;
snow.y += snow.ySpeed;
if (snow.x < -snow.bpWidth || snow.x > getWidth()) {
/**
* the snow falling to the sides
*/
if (isDelyStop)
snowList.remove(i);
else {
snow.x = randomX(snow.bpWidth);
snow.y = randomY(snow.bpHeight);
}
} else if (snow.y > getHeight()) {
/**
* the snow falling to the bottom
*/
if (isDelyStop)
snowList.remove(i);
else {
snow.x = randomX(snow.bpWidth);
snow.y = randomY(snow.bpHeight);
}
}
Log.d("TAG", "snow.x:" + snow.x);
Log.d("TAG", "snow.Y:" + snow.y);
}
/**
* to prevent the animator running empty
*/
if (snowList.size() <= 0 && animator.isRunning())
animator.cancel();
invalidate();
}
}
class Snow {
private float x;
private float y;
private float xSpeed;
private float ySpeed;
private int bpHeight;
private int bpWidth;
private Bitmap snowBitmap;
private float BASESPEED = 100.0f;
Snow(float xSpeed, float ySpeed, Bitmap snowBitmap) {
float tempScale = minScale + (float) (Math.random() * (maxScale - minScale));
this.bpHeight = (int) (snowBitmap.getHeight() * tempScale);
this.bpWidth = (int) (snowBitmap.getWidth() * tempScale);
this.x = randomX(bpWidth);
this.y = randomY(bpHeight);
/**
* xDirection > 0 right falling
* xDirection < 0 left falling
* xDirection = 0 vertical falling
*/
float xDirection = 1.0f - (float) (Math.random() * 2.0f);
// this.xSpeed = xSpeed * xDirection / BASESPEED;
this.xSpeed = (xSpeed + (xSpeed * 6) * (float) Math.random()) / BASESPEED;
this.ySpeed = (ySpeed + (ySpeed * 3) * (float) Math.random()) / BASESPEED;
this.snowBitmap = Bitmap.createScaledBitmap(snowBitmap, bpWidth, bpHeight, true);
}
}
/**
* the x coordinate
*/
private float randomX(int bpWidth) {
return initToLeft + xRandom.nextFloat() * (xWidth - bpWidth) - 1000;
}
/**
* the y coordinate
*/
private float randomY(int bpHeight) {
return (initToTop + yRandom.nextFloat() * (yHeight - bpHeight)) - 800;
}
}
动画的属性定义
<declare-styleable name="SnowFlyView">
<attr name="snow_initTo" format="dimension" />
<attr name="snow_initToTop" format="dimension" />
<attr name="snow_initToLeft" format="dimension" />
<attr name="snow_initToBottom" format="dimension" />
<attr name="snow_initToRight" format="dimension" />
<attr name="snow_minScale" format="float" />
<attr name="snow_maxScale" format="float" />
<attr name="snow_count" format="integer" />
<attr name="snow_duration" format="integer" />
<attr name="snow_xSpeed" format="float" />
<attr name="snow_ySpeed" format="float" />
<attr name="snow_bitmap" format="reference" />
</declare-styleable>
使用方法也很简单,在你要用的页面中放这个view空间 范围可以自己定, 使用方法如下,自己定义图片 飘落速度 等
flowerFlaySfv.setSnowDuration(300);
ArrayList<Drawable> imageList = new ArrayList<>();
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake1,null));
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake2,null));
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake3,null));
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake4,null));
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake5,null));
imageList.add(mContext.getResources().getDrawable(R.mipmap.snowflake6,null));
flowerFlaySfv.setImageDrawableList(imageList);
flowerFlaySfv.startAnimation();
ok 就这样,自己想飘落什么飘落什么 ,当然如果觉得 风力太小 可以修改自定义控件,这个就不讲了 自己研究下,自己学会的才是自己的。