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>
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??
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.
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);
}
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With