Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edited: Android Draw needle image to this circle similar to meter guage

So far i am able to draw semi circle using some code reference form stackoverflow. Now i wish to draw needle to this semi circle. I have no idea as how to do it. Here is the Semi circle code

    package in.ashish29agre.stackoverflow.sample.semicircle;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.View;

public class MyGraphView extends View {
    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private float[] value_degree;
    private int[] COLORS = { Color.GREEN, Color.RED,  Color.GREEN, Color.RED };
    // size of bigger half circle
    RectF rectf = null;
    // size of smaller half circle
//    RectF rectf2 = new RectF(45, 45, 275, 275);
    // size of the smallest half circle
//    RectF rectf3 = new RectF(80, 80, 240, 240);

    int temp = 0;

    public MyGraphView(Context context, float[] values) {

        super(context);
        rectf = new RectF();
        value_degree = new float[values.length];
        for (int i = 0; i < values.length; i++) {
            value_degree[i] = values[i];
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        rectf.set(100, 100, width - 100, height - 100);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);


        for (int i = 0; i < value_degree.length; i++) {
            // set type of "brush"
            paint.setStrokeWidth(128);
            paint.setStyle(Paint.Style.STROKE);
                    // agree
            if (i == 0) {
                final Path path = new Path();
                paint.setColor(COLORS[i]);
                // draw 3 paths to show 3 curves
                path.addArc(rectf, 180, value_degree[i] - 4);
//                path.addArc(rectf2, 180, value_degree[i] - 5);
//                path.addArc(rectf3, 180, value_degree[i] - 6);
                // draw the path
                canvas.drawPath(path, paint);

                // disagree
            } else {
                temp += (int) value_degree[i - 1];
                paint.setColor(COLORS[i]);
                final Path path = new Path();
                path.addArc(rectf, temp + 180 , value_degree[i] - 0);
//                path.addArc(rectf2, temp + 180 + 5, value_degree[i] - 5);
//                path.addArc(rectf3, temp + 180 + 6, value_degree[i] - 6);
                // draw the path
                canvas.drawPath(path, paint);
            }


            drawLine(canvas);

        }
    }
    private void drawLine(Canvas canvas) {
        float startAngle = 180;
        float sweepAngle = 180;
        Paint mPaint = new Paint();
        mPaint.setStrokeWidth(22f);
        mPaint.setColor(Color.BLACK);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        float startX = rectf.centerX();
        float startY = rectf.centerY();
        float radius = rectf.centerX() - 100;
        float angle = (float) ((startAngle + sweepAngle / 2) * Math.PI / 180);
        float stopX = (float) (startX + radius * Math.cos(angle));
        float stopY = (float) (startY + radius * Math.sin(angle));

        canvas.drawLine(startX, startY, stopX, stopY, mPaint);
    }


}

From the Activity i call it using

float values[] = { 10, 20, 30, 40};
LinearLayout linear = (LinearLayout) findViewById(R.id.graph_view);
        values = calculateData(values);
        // draw the graf
        linear.addView(new MyGraphView(this, values));

This is my activity xml code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="in.ashish29agre.stackoverflow.sample.semicircle.SemiCircleActivity">

    <LinearLayout
        android:id="@+id/graph_view"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:orientation="vertical"
        android:layout_centerInParent="true"
        android:layout_alignParentTop="true"></LinearLayout>
</RelativeLayout>

enter image description here

Currently the view looks like this now i wish to add meter hand which can move from 0-180 degree.

Any help will be appreciated.

Now that i have drawn needle i wish to make to a needle bitmap??

like image 543
silentsudo Avatar asked Jan 30 '16 13:01

silentsudo


3 Answers

You may want to animate the needle bitmap. Here is my code:

RotateAnimation animation = 
    new RotateAnimation(
        mCurrentAngle,
        toAngle,
        Animation.RELATIVE_TO_SELF,
        pivotX,
        Animation.RELATIVE_TO_SELF, 
        pivotY);

animation.setRepeatCount(0);
animation.setFillAfter(true);
animation.setFillEnabled(true);
animation.setInterpolator(new OvershootInterpolator());
animation.setDuration(duration);
mMeterPointer.startAnimation(animation);

Where mMeterPointer is an ImageView of the needle.

The pivotX and pivotY values should where the needle image should rotate. Their values should be 0 to 1, e.g. 0.5 and 0.5 if you want it to rotate on the middle of the bitmap.

like image 178
John Bennedict Lorenzo Avatar answered Oct 12 '22 23:10

John Bennedict Lorenzo


Add to your class:

Matrix matrix;
Bitmap needle;

to your MyGraphView constructor:

matrix = new Matrix();

and this to the end of onMeasure():

needle = decodeSampledBitmapFromResource(context.getResources(),
            R.drawable.icon_resource, (int)rectf.width(), (int)rectf.height());

and in drawLine():

private void drawLine(Canvas canvas) {
    float startAngle = 180;
    float sweepAngle = 180;

    // of course you'll need to calculate the actual angle here:
    float angle = (float) ((startAngle + sweepAngle / 2) * Math.PI / 180);

    matrix.reset();
    // move the needle to IT's center. You might need different
    // values depending on your drawable, probably the axis will not
    // be in the middle
    matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getWidth() / 2);
    // and rotate it
    matrix.postRotate(angle);

    // move the needle to the semi circle's center
    matrix.postTranslate(rectf.centerX(), rectf.centerY());
    canvas.drawBitmap(needle, matrix, null);
}

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
        int reqWidth, int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeResource(res, resId, options);

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeResource(res, resId, options);
}
like image 29
Gavriel Avatar answered Oct 12 '22 23:10

Gavriel


Adding to @bennegeek's answer can you try this

private void setAngleToNeedle() {
int value = 675;
int maxValue = 1000;
int angleDifference = 180;
int endingAngle = (int) (((float) value / maxValue) * (angleDifference));
final RotateAnimation rotateAnim = new RotateAnimation(-90, -90 + endingAngle,
RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 1f);


rotateAnim.setDuration(1500);
rotateAnim.setInterpolator(new LinearInterpolator());
rotateAnim.setFillAfter(true);
needleIv.startAnimation(rotateAnim);
}
like image 21
Deekshith R Moolya Avatar answered Oct 13 '22 00:10

Deekshith R Moolya