Sunday, April 30, 2017

Android - Moving an object on a circular path


Overview: -  Android provides powerful API libraries which support custom 2D and 3D graphics. We can move an object on the circular path by using canvas and doing some mathematics calculation.



You can use the parametric equation of a circle. Considering the circle is drawn with the center on the origin (O) as shown in the diagram below



If we take a point "p" on the circumference of the circle, having a radius r.

Let the angle made by OP (Origin to p) be θ. Let the distance of p from x-axis be y Let the distance of p from y-axis be x

Using the above assumptions we get the triangle as shown below:

Now we know that cos θ = base/hypotenuse and sin θ = perpendicular/hypotenuse

which gives us cos θ = x/r and sin θ = y/r

If the circle is not at the origin and rather at (a,b) then we can say that the center of the circle is shifted

a unit in the x-axis
b unit in the y-axis 

So for such a circle, we can change the parametric equation accordingly by adding the shift on the x and y-axis giving us the following equations:

x=a+r*cosθ
y=b+r*sinθ 

Where a & b are the x,y coordinates of the center of the circle.

Hence we found x and y the coordinates of the point on the circumference of the circle with radius r

By using the above calculation, We can move an object by using the above method. As we can see:






Now, Let's implement it in Android.

To implement it, we going to use SurfaceView.

import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class CircularView extends SurfaceView implements SurfaceHolder.Callback2 {

    private SurfaceHolder mHolder;

    private int mViewWidth;
    private int mViewHeight;
    private Circle mBigCircle;

    private AnimationThread galleryThread = null;

    public CircularView(Context context) {
        super(context);

        mHolder = getHolder();

        mHolder.addCallback(this);
    }

    @Override
    public void surfaceRedrawNeeded(SurfaceHolder holder) {
        drawViewOnSystemCall(holder);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mViewWidth = getWidth();
        mViewHeight = getHeight();

        mBigCircle = new Circle(mViewWidth / 2, mViewHeight / 2, (Math.round((mViewWidth * 80)          / 100)) / 2);

        drawViewOnSystemCall(holder);

        galleryThread = new AnimationThread(getHolder());
        galleryThread.setRunning(true);
        galleryThread.start();
    }

    private void drawViewOnSystemCall(SurfaceHolder holder) {
        synchronized (holder) {
            refreshScreen();
        }
    }

    private void refreshScreen() {
        Canvas lockCanvas = mHolder.lockCanvas();
        drawSurfaceView(lockCanvas);
        mHolder.unlockCanvasAndPost(lockCanvas);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        drawViewOnSystemCall(holder);
    }

    private void drawSurfaceView(Canvas canvas) {
        if (canvas == null) {
            return;
        }
        canvas.drawRGB(255, 255, 255);
        if (mBigCircle != null) {
            mBigCircle.render(canvas);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    class AnimationThread extends Thread {
        private boolean isRunning;
        private SurfaceHolder mHolder;

        public AnimationThread(SurfaceHolder holder) {
            mHolder = holder;
        }

        public void setRunning(boolean running) {
            isRunning = running;
        }

        @Override
        public void run() {
            while (isRunning) {
                mBigCircle.move();
                drawViewOnSystemCall(mHolder);
            }
        }
    }
}

Create a circle object that shows a circle border and moving object.

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;

public class Circle {

    private float mUserPicCenterX;
    private float mUserPicCenterY;

    private float mUserPicBorderCenterX;
    private float mUserPicBorderCenterY;
    private int mBorderRadius;
    private Paint mVisiblePaint;
    private Paint mVisibleMessageCountPaint;
    private double angle = 230;
    private int mVisibleMessageCountRadius;

    public Circle(float centerX, float centerY, int radius) {
        mUserPicCenterX = centerX;
        mUserPicCenterY = centerY;
        mBorderRadius = radius;
        createVisiblePaint();
        updatePosition(angle);
    }


    private void updatePosition(double angle) {
        angle = Math.toRadians(angle);
        mUserPicBorderCenterX = (float) (mUserPicCenterX + Math.cos(angle) * mBorderRadius);
        mUserPicBorderCenterY = (float) (mUserPicCenterY + Math.sin(angle) * mBorderRadius);
    }

    private void createVisiblePaint() {
        mVisiblePaint = new Paint();
        mVisiblePaint.setAntiAlias(true);
        mVisiblePaint.setFilterBitmap(true);
        mVisiblePaint.setDither(true);
        mVisiblePaint.setColor(Color.parseColor("#F85A74"));
        mVisiblePaint.setStyle(Paint.Style.STROKE);
        mVisiblePaint.setStrokeWidth(14f);

        mVisibleMessageCountPaint = new Paint();
        mVisibleMessageCountPaint.setAntiAlias(true);
        mVisibleMessageCountPaint.setFilterBitmap(true);
        mVisibleMessageCountPaint.setDither(true);
        mVisibleMessageCountPaint.setColor(Color.parseColor("#F85A74"));

        mVisibleMessageCountRadius = mBorderRadius / 6;

    }

    public void render(Canvas canvas) {
        canvas.drawCircle(mUserPicCenterX, mUserPicCenterY, mBorderRadius, mVisiblePaint);
        canvas.drawCircle(mUserPicBorderCenterX, mUserPicBorderCenterY, mVisibleMessageCountRadius, mVisibleMessageCountPaint);
    }


    public void move() {
        if (angle > 360) {
            angle = 0;
        }
        angle++;
        updatePosition(angle);
    }
}

Share:

Get it on Google Play

React Native - Start Development with Typescript

React Native is a popular framework for building mobile apps for both Android and iOS. It allows developers to write JavaScript code that ca...