Mobile Development 13 min read

Create Stunning Firework Like Effects for Android Likes with Canvas and Animators

This tutorial explains how to implement a firework‑style like animation in Android by defining particle objects, drawing them on a Canvas, controlling their motion with ValueAnimator and various interpolators, and assembling the animation sequence to produce a festive, high‑frame‑rate visual effect.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Create Stunning Firework Like Effects for Android Likes with Canvas and Animators

Introduction

Using a firework‑style like effect is a common way to boost user interaction in apps. This guide shows how to build such an effect with holiday icons, creating a festive atmosphere and increasing user engagement.

Effect Screenshot

Firework effect preview
Firework effect preview

Implementation Overview

The firework effect consists of two main parts: particles emitted from a launch point and spark particles generated after the explosion. Each particle holds a bitmap and is drawn on a Canvas, forming the overall firework pattern.

1. Define Particle Object

public class Particle {
    Matrix mMatrix;
    Paint mPaint;
    Bitmap mImage;

    float mInitialX, mInitialY; // initial position
    float mSpeedX, mSpeedY; // speed (px/ms)
    float mRotation; // rotation angle

    float mScale = 1f; // scale
    int mAlpha = 255; // opacity
    float mCurrentX, mCurrentY; // current position

    protected Particle(Bitmap bitmap) {
        mMatrix = new Matrix();
        mPaint = new Paint();
        mImage = bitmap;
    }

    public boolean update(long miliseconds) {
        updateLocation(this, miliseconds);
        updateScale(this, miliseconds);
        updateAlpha(this, miliseconds);
        return true;
    }

    public void draw(Canvas c) {
        mMatrix.reset();
        mMatrix.postRotate(mRotation, mBitmapHalfWidth, mBitmapHalfHeight);
        mMatrix.postScale(mScale, mScale, mBitmapHalfWidth, mBitmapHalfHeight);
        mMatrix.postTranslate(mCurrentX, mCurrentY);
        mPaint.setAlpha(mAlpha);
        c.drawBitmap(mImage, mMatrix, mPaint);
    }
}

2. Draw on Canvas

public class ParticleLikeFieldView extends View {
    List<Particle> fireworkList; // firework particles
    List<List<Particle>> sparkOuterList; // outer spark group
    List<List<Particle>> sparkInnerList; // inner spark group
    boolean isFireworkDead = false; // explosion state

    @Override
    protected void onDraw(Canvas canvas) {
        synchronized (this) {
            if (!isFireworkDead) {
                for (Particle p : fireworkList) {
                    p.draw(canvas);
                }
            } else {
                for (List<Particle> outer : sparkOuterList) {
                    for (Particle p : outer) {
                        p.draw(canvas);
                    }
                }
                for (List<Particle> inner : sparkInnerList) {
                    for (Particle p : inner) {
                        p.draw(canvas);
                    }
                }
            }
        }
    }
}

3. Add and Remove the Drawing View

private void addDrawingView() {
    ParticleLikeFieldView mDrawingView = new ParticleLikeFieldView(context);
    ViewGroup mParentView = (ViewGroup) activity.findViewById(android.R.id.content);
    mParentView.addView(mDrawingView);
}

private void cleanupDrawingView() {
    mParentView.removeView(mDrawingView);
    mParentView.postInvalidate();
    mDrawingView = null;
}

4. Create Animations

The animation sequence is split into several ValueAnimators:

fireworkAnim – launches the firework (800 ms)

sparkOuterAnim – outer spark expansion (300 ms)

sparkInnerAnim – inner spark expansion (300 ms)

nullOuterAnim – pause before inner sparks (100 ms)

fireworkAnim Example

ValueAnimator fireworkAnim = ValueAnimator.ofInt(0, fireworkDuration);
fireworkAnim.setDuration(fireworkDuration);
fireworkAnim.setInterpolator(new DecelerateInterpolator());
fireworkAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int miliseconds = (Integer) animation.getAnimatedValue();
        particle.update(miliseconds);
        mDrawingView.postInvalidate();
    }
});
fireworkAnim.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationEnd(Animator animation) {
        mDrawingView.isFireworkDead = true;
    }
    @Override
    public void onAnimationCancel(Animator animation) {
        cleanupDrawingView();
    }
    // other callbacks omitted for brevity
});

Combine Animations

AnimatorSet set = new AnimatorSet();
set.play(fireworkAnim).before(sparkOuterAnim);
set.play(sparkOuterAnim).with(nullOuterAnim);
set.play(nullOuterAnim).before(sparkInnerAnim);
set.start();

5. Interpolators

Interpolators map the animation progress (0‑1) to a fraction that determines the speed curve.

TimeInterpolator Interface

public interface TimeInterpolator {
    float getInterpolation(float input);
}

LinearInterpolator (constant speed)

public float getInterpolation(float input) {
    return input;
}

AccelerateDecelerateInterpolator (ease‑in‑ease‑out)

public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f);
}
AccelerateDecelerateInterpolator curve
AccelerateDecelerateInterpolator curve

CycleInterpolator (repeating)

public float getInterpolation(float input) {
    return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
CycleInterpolator wave
CycleInterpolator wave

Particle Property Calculations

1. Determine Launch Position

int[] location = new int[2];
emitter.getLocationInWindow(location);
int emitterX = location[0] + emitter.getWidth() / 2;
int emitterY = location[1] + emitter.getHeight() / 2;
particle.mInitialX = emitterX - mBitmapHalfWidth;
particle.mInitialY = emitterY - mBitmapHalfHeight;
particle.mCurrentX = particle.mInitialX;
particle.mCurrentY = particle.mInitialY;

2. Initial Speed and Angle

int angle = random.nextInt(maxAngle - minAngle) + minAngle;
float angleOuter = 45 * (n - 1); // outer spark
float angleInner = 45 * (n - 1); // inner spark
double angleInRads = Math.toRadians(angle);
particle.mSpeedX = (float) (speed * Math.cos(angleInRads));
particle.mSpeedY = (float) (speed * Math.sin(angleInRads));
particle.mRotation = angle + 90;

3. Scale

float mInitialValue = 1.0f;
float mFinalValue = 2.0f;
Interpolator mInterpolator = new LinearInterpolator();

public boolean updateScale(Particle particle, long ms, long start, long end) {
    if (ms < start) {
        particle.mScale = mInitialValue;
    } else if (ms > end) {
        particle.mScale = mFinalValue;
    } else {
        float input = (ms - start) * 1f / (end - start);
        float fraction = mInterpolator.getInterpolation(input);
        particle.mScale = mInitialValue + (mFinalValue - mInitialValue) * fraction;
    }
    return true;
}

4. Opacity

int mInitialValue = 255;
int mFinalValue = 0;
Interpolator mInterpolator = new AccelerateInterpolator();

public boolean updateAlpha(Particle particle, long ms, long start, long end) {
    if (ms < start) {
        particle.mAlpha = mInitialValue;
    } else if (ms > end) {
        particle.mAlpha = mFinalValue;
    } else {
        float input = (ms - start) * 1f / (end - start);
        float fraction = mInterpolator.getInterpolation(input);
        particle.mAlpha = (int) (mInitialValue + (mFinalValue - mInitialValue) * fraction);
    }
    return true;
}

5. Position Update

public boolean updateLocation(Particle particle, long ms) {
    particle.mCurrentX = mInitialX + mSpeedX * ms;
    particle.mCurrentY = mInitialY + mSpeedY * ms;
    return true;
}

Conclusion

Using Canvas to render high‑frame‑rate particle effects provides a flexible way to create custom animations on Android. Property animators and the rich set of interpolators (including custom ones) enable fine‑grained control over speed curves, making it easy to build fireworks, bubbles, lens‑flaring, and many other visual effects.

AndroidCanvasInterpolatorUI EffectsValueAnimatorParticle Animation
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.