爆炸消失特效

需要用到自定义动画,工具类如下:


public class ExplosionAnimator extends ValueAnimator{

public static final int DEFAULT_DURATION = 1500;
private Particle[][] mParticles;
private Paint mPaint;
private View mContainer;

public ExplosionAnimator(View view, Bitmap bitmap, Rect bound) {

    mPaint = new Paint();
    mContainer = view;

    setFloatValues(0.0f, 1.0f);
    setDuration(DEFAULT_DURATION);

    mParticles = generateParticles(bitmap, bound);
}

private Particle[][] generateParticles(Bitmap bitmap, Rect bound) {
    int w = bound.width();
    int h = bound.height();

    int partW_Count = w / Particle.PART_WH; //横向个数
    int partH_Count = h / Particle.PART_WH; //竖向个数

    int bitmap_part_w = bitmap.getWidth() / partW_Count;
    int bitmap_part_h = bitmap.getHeight() / partH_Count;

    Particle[][] particles = new Particle[partH_Count][partW_Count];
    Point point = null;
    for (int row = 0; row < partH_Count; row ++) { //行
        for (int column = 0; column < partW_Count; column ++) { //列
            //取得当前粒子所在位置的颜色
            int color = bitmap.getPixel(column * bitmap_part_w, row * bitmap_part_h);

            point = new Point(column, row); //x是列,y是行

            particles[row][column] = Particle.generateParticle(color, bound, point);
        }
    }

    return particles;
}

public void draw(Canvas canvas) {
    if(!isStarted()) { //动画结束时停止
        return;
    }
    for (Particle[] particle : mParticles) {
        for (Particle p : particle) {
            p.advance((Float) getAnimatedValue());
            mPaint.setColor(p.color);

// mPaint.setAlpha((int) (255 * p.alpha)); //只是这样设置,透明色会显示为黑色
mPaint.setAlpha((int) (Color.alpha(p.color) * p.alpha)); //这样透明颜色就不是黑色了
canvas.drawCircle(p.cx, p.cy, p.radius, mPaint);
}
}

    mContainer.invalidate();
}

@Override
public void start() {
    super.start();
    mContainer.invalidate();
}

}


public class ExplosionField extends View{
private static final String TAG = “ExplosionField”;
private static final Canvas mCanvas = new Canvas();
private ArrayList explosionAnimators;
private OnClickListener onClickListener;

public ExplosionField(Context context) {
    super(context);
    init();
}

public ExplosionField(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}
private void init() {
    explosionAnimators = new ArrayList<ExplosionAnimator>();

    attach2Activity((Activity) getContext());
}
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    for (ExplosionAnimator animator : explosionAnimators) {
        animator.draw(canvas);
    }
}

/**
 * 爆破
 * @param view 使得该view爆破
 */
public void explode(final View view) {
    Rect rect = new Rect();
    view.getGlobalVisibleRect(rect); //得到view相对于整个屏幕的坐标
    rect.offset(0, -Utils.dp2px(25)); //去掉状态栏高度

    final ExplosionAnimator animator = new ExplosionAnimator(this, createBitmapFromView(view), rect);
    explosionAnimators.add(animator);

    animator.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationStart(Animator animation) {
            view.animate().alpha(0f).setDuration(150).start();
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            view.animate().alpha(1f).setDuration(150).start();

            //动画结束时从动画集中移除
            explosionAnimators.remove(animation);
            animation = null;
        }
    });
    animator.start();
}

private Bitmap createBitmapFromView(View view) {
    /*
     * 为什么屏蔽以下代码段?
     * 如果ImageView直接得到位图,那么当它设置背景(backgroud)时,不会读取到背景颜色
     */

// if (view instanceof ImageView) {
// Drawable drawable = ((ImageView)view).getDrawable();
// if (drawable != null && drawable instanceof BitmapDrawable) {
// return ((BitmapDrawable) drawable).getBitmap();
// }
// }

    //view.clearFocus(); //不同焦点状态显示的可能不同——(azz:不同就不同有什么关系?)

    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);

    if (bitmap != null) {
        synchronized (mCanvas) {
            mCanvas.setBitmap(bitmap);
            view.draw(mCanvas);
            mCanvas.setBitmap(null); //清除引用
        }
    }
    return bitmap;
}

/**
 * 给Activity加上全屏覆盖的ExplosionField
 */
private void attach2Activity(Activity activity) {
    ViewGroup rootView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);

    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
    rootView.addView(this, lp);
}


/**
 * 希望谁有破碎效果,就给谁加Listener
 * @param view 可以是ViewGroup
 */
public void addListener(View view) {
    if (view instanceof ViewGroup) {
        ViewGroup viewGroup = (ViewGroup) view;
        int count = viewGroup.getChildCount();
        for (int i = 0 ; i < count; i++) {
            addListener(viewGroup.getChildAt(i));
        }
    } else {
        view.setClickable(true);
        view.setOnClickListener(getOnClickListener());
    }
}


private OnClickListener getOnClickListener() {
    if (null == onClickListener) {

        onClickListener = new OnClickListener() {
            @Override
            public void onClick(View v) {
                ExplosionField.this.explode(v);

// view.setOnClickListener(null); // 用过一次就不需要了
}
};
}

    return onClickListener;
}

}


/*
* 爆破粒子
*/
public class Particle {

public static final int PART_WH = 8; //默认小球宽高

//原本的值(不可变)

// float originCX;
// float originCY;
// float originRadius;

//实际的值(可变)
float cx; //center x of circle
float cy; //center y of circle
float radius;

int color;
float alpha;

static Random random = new Random();

Rect mBound;

public static Particle generateParticle(int color, Rect bound, Point point) {
    int row = point.y; //行是高
    int column = point.x; //列是宽

    Particle particle = new Particle();
    particle.mBound = bound;
    particle.color = color;
    particle.alpha = 1f;

    particle.radius = PART_WH;
    particle.cx = bound.left + PART_WH * column;
    particle.cy = bound.top + PART_WH * row;

    return particle;
}

public void advance(float factor) {
    cx = cx + factor * random.nextInt(mBound.width()) * (random.nextFloat() - 0.5f);
    cy = cy + factor * random.nextInt(mBound.height() / 2);

    radius = radius - factor * random.nextInt(2);

    alpha = (1f - factor) * (1 + random.nextFloat());
}

}


public class Utils {
/**
* 密度
*/
public static final float DENSITY = Resources.getSystem().getDisplayMetrics().density;

public static int dp2px(int dp) {
    return Math.round(dp * DENSITY);
}

}


//爆破效果
//实现爆炸动画只需实例化工具类即可,Layout指要有爆炸效果的布局
ExplosionField explosionField = new ExplosionField(this);
explosionField.addListener(Layout);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值