Bubble animation for Android


This example shares the specific code of Android bubble animation for your reference. The specific contents are as follows

1、 Foreword

Originally wanted to do an animation effect similar to window bubble screensaver.

However, the formula of non centripetal collision between small balls has not been studied. It is really too complex for me. When the formula is almost the same, I find that the problem of calculation angle is also very complex. The blogger said that he never passed physics in high school, and this is a college physics course… However, I didn’t study physics in college.
At present, the effect is also very simple, but the boundary collision is detected. The principle is momentum conservation and velocity exchange.
The actual effect is as smooth as silk. GIF recorded the frame.

2、 Implementation code

It’s not encapsulated this time. It’s only a semi-finished product anyway. It says to play.

Used a very good library: Click to view, randomly generate good-looking colors, written by Chinese, powerful.

 * Created by AItsuki on 2016/1/12.
public class BallView extends View {

    private final Random mRandom;

    class Ball {
        int radius; //  radius
        float cx;   //  center of a circle
        float cy;   //  center of a circle
        float vx; //  X-axis speed
        float vy; //  Y-axis speed
        Paint paint;

        void move() {
            //Move in the direction of the angle to offset the center of the circle
            cx += vx;
            cy += vy;

        int left() {
            return (int) (cx - radius);

        int right() {
            return (int) (cx +radius);

        int bottom() {
            return (int) (cy + radius);

        int top() {
            return (int) (cy - radius);

    private int mCount = 40;   //  Number of small balls
    private int maxRadius;  //  Maximum radius of small ball
    private int minRadius; //  Minimum radius of small ball
    private int minSpeed = 5; //  Minimum moving speed of small ball
    private int maxSpeed = 20; //  Maximum movement speed of small ball

    private int mWidth = 200;
    private int mHeight = 200;

    public Ball[] mBalls;   //  An array that holds all the balls

    public BallView(Context context, AttributeSet attrs) {
        super(context, attrs);

        //Initialize all balls (set colors and brushes, initialize the angle of movement)
        mRandom = new Random();
        RandomColor randomColor = new RandomColor(); //  Randomly generate good-looking colors, GitHub open source library.
        mBalls = new Ball[mCount];

        for(int i=0; i< mCount; i++) {
            mBalls[i] = new Ball();
            //Set brush
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

            //Set speed
            float speedX = (mRandom.nextInt(maxSpeed -minSpeed +1)+5)/10f;
            float speedY = (mRandom.nextInt(maxSpeed -minSpeed +1)+5)/10f;
            mBalls[i].paint = paint;
            mBalls[i].vx = mRandom.nextBoolean() ? speedX : -speedX;
            mBalls[i].vy = mRandom.nextBoolean() ? speedY : -speedY;

        //It is only set when the center and radius of the circle are measured

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = resolveSize(mWidth, widthMeasureSpec);
        mHeight = resolveSize(mHeight, heightMeasureSpec);
        setMeasuredDimension(mWidth, mHeight);
        maxRadius = mWidth/12;
        minRadius = maxRadius/2;

        //Initializes the radius and center of a circle
        for (int i=0; i<mBalls.length; i++) {
            mBalls[i].radius = mRandom.nextInt(maxRadius+1 - minRadius) +minRadius;
//            mBalls[i].mass = (int) (Math.PI * mBalls[i].radius * mBalls[i].radius);
            //Initialize the position of the center of the circle. The minimum x is radius and the maximum is mwidth radius
            mBalls[i].cx = mRandom.nextInt(mWidth - mBalls[i].radius) + mBalls[i].radius;
            mBalls[i].cy = mRandom.nextInt(mHeight - mBalls[i].radius) + mBalls[i].radius;


    protected void onDraw(Canvas canvas) {
        long startTime = System.currentTimeMillis();

        //Draw all the circles first
        for (int i = 0; i < mCount; i++) {
            Ball ball = mBalls[i];
            canvas.drawCircle(ball.cx, ball.cy, ball.radius, ball.paint);

        //Ball collision boundary
        for (int i = 0; i < mCount; i++) {
            Ball ball = mBalls[i];
            collisionDetectingAndChangeSpeed(ball); //  Calculation of collision boundary
            ball.move(); //Move

        long stopTime = System.currentTimeMillis();
        long runTime = stopTime - startTime;
        //Once every 16 milliseconds
        postInvalidateDelayed(Math.abs(runTime -16));


    //Judge whether the ball collides with the collision boundary
    public void collisionDetectingAndChangeSpeed(Ball ball) {
        int left = getLeft();
        int top = getTop();
        int right = getRight();
        int bottom = getBottom();

        float speedX = ball.vx;
        float speedY = ball.vy;

        //The velocity of X is reversed around the collision. The judgment of speed is to prevent repeated collision detection, and then stick it to the wall ==
        if(ball.left() <= left && speedX < 0) {
            ball.vx = -ball.vx;
        } else if(ball.top() <= top && speedY < 0) {
            ball.vy = -ball.vy;
        } else if(ball.right() >= right && speedX >0) {
            ball.vx = -ball.vx;
        } else if(ball.bottom() >= bottom && speedY >0) {
            ball.vy = -ball.vy;


The code can be copied directly, so the demo download is not provided.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.

Recommended Today

Swift advanced (XV) extension

The extension in swift is somewhat similar to the category in OC Extension can beenumeration、structural morphology、class、agreementAdd new features□ you can add methods, calculation attributes, subscripts, (convenient) initializers, nested types, protocols, etc What extensions can’t do:□ original functions cannot be overwritten□ you cannot add storage attributes or add attribute observers to existing attributes□ cannot add parent […]