Android: Looking for a Drawarc() Method with Inner & Outer Radius

Android: looking for a drawArc() method with inner & outer radius

You can paint over the inner area using the PorterDuff xfermode called "Clear." This will erase pixels.

Android: Drawing an arc inside a circle

The following custom View draws two arcs connecting to form a circle as well as an inner circle.

Sample Image

Moreover, I let it fill the rectangle used for drawing the arc and use a yellow background for the View, the activity background is dark. (These additional features are meant for getting a better impression of how drawing a circle / an arc works, they can help with debugging.)

The custom View:

public class MySimpleView extends View{

private static final int STROKE_WIDTH = 20;
private Paint mBasePaint, mDegreesPaint, mCenterPaint, mRectPaint;
private RectF mRect;
private int centerX, centerY, radius;

public MySimpleView(Context context) {
super(context);
init();
}

public MySimpleView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

public MySimpleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

private void init()
{
mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mRectPaint.setColor(ContextCompat.getColor(getContext(), R.color.magenta));
mRectPaint.setStyle(Paint.Style.FILL);

mCenterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterPaint.setColor(ContextCompat.getColor(getContext(), R.color.white));
mCenterPaint.setStyle(Paint.Style.FILL);

mBasePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBasePaint.setStyle(Paint.Style.STROKE);
mBasePaint.setStrokeWidth(STROKE_WIDTH);
mBasePaint.setColor(ContextCompat.getColor(getContext(), R.color.blue));

mDegreesPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDegreesPaint.setStyle(Paint.Style.STROKE);
mDegreesPaint.setStrokeWidth(STROKE_WIDTH);
mDegreesPaint.setColor(ContextCompat.getColor(getContext(), R.color.green));

}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// getHeight() is not reliable, use getMeasuredHeight() on first run:
// Note: mRect will also be null after a configuration change,
// so in this case the new measured height and width values will be used:
if (mRect == null)
{
// take the minimum of width and height here to be on he safe side:
centerX = getMeasuredWidth()/ 2;
centerY = getMeasuredHeight()/ 2;
radius = Math.min(centerX,centerY);

// mRect will define the drawing space for drawArc()
// We have to take into account the STROKE_WIDTH with drawArc() as well as drawCircle():
// circles as well as arcs are drawn 50% outside of the bounds defined by the radius (radius for arcs is calculated from the rectangle mRect).
// So if mRect is too large, the lines will not fit into the View
int startTop = STROKE_WIDTH / 2;
int startLeft = startTop;

int endBottom = 2 * radius - startTop;
int endRight = endBottom;

mRect = new RectF(startTop, startLeft, endRight, endBottom);
}

// just to show the rectangle bounds:
canvas.drawRect(mRect, mRectPaint);

// subtract half the stroke width from radius so the blue circle fits inside the View
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH / 2, mBasePaint);
// Or draw arc from degree 192 to degree 90 like this ( 258 = (360 - 192) + 90:
// canvas.drawArc(mRect, 192, 258, false, mBasePaint);

// draw an arc from 90 degrees to 192 degrees (102 = 192 - 90)
// Note that these degrees are not like mathematical degrees:
// they are mirrored along the y-axis and so incremented clockwise (zero degrees is always on the right hand side of the x-axis)
canvas.drawArc(mRect, 90, 102, false, mDegreesPaint);

// subtract stroke width from radius so the white circle does not cover the blue circle/ arc
canvas.drawCircle(centerX, centerY, radius - STROKE_WIDTH, mCenterPaint);
}
}

How to draw an arc segment with different fill and stroke colors for each side?

You need to draw the parts of the ring segment separately with different paints directly via draw* methods from the same calculated endpoints as the filling's bounds. The Path is still needed for filling it though. I went one step further and split your strokeAll to strokeSides+strokeOuter for easier reuse. Consider the following bunch of lines:

/**
* Draws a thick arc between the defined angles, see {@link Canvas#drawArc} for more.
* This method is equivalent to
* <pre><code>
* float rMid = (rInn + rOut) / 2;
* paint.setStyle(Style.STROKE); // there's nothing to fill
* paint.setStrokeWidth(rOut - rInn); // thickness
* canvas.drawArc(new RectF(cx - rMid, cy - rMid, cx + rMid, cy + rMid), startAngle, sweepAngle, false, paint);
* </code></pre>
* but supports different fill and stroke paints.
*
* @param cx horizontal middle point of the oval
* @param cy vertical middle point of the oval
* @param rInn inner radius of the arc segment
* @param rOut outer radius of the arc segment
* @param startAngle see {@link Canvas#drawArc}
* @param sweepAngle see {@link Canvas#drawArc}, capped at ±360
* @param fill filling paint, can be <code>null</code>
* @param strokeInner stroke paint for inner ring segment, can be <code>null</code>
* @param strokeOuter stroke paint for outer ring segment, can be <code>null</code>
* @param strokeSides stroke paint for lines connecting the ends of the ring segments, can be <code>null</code>
* @see Canvas#drawArc
*/
public static void drawArcSegment(Canvas canvas, float cx, float cy, float rInn, float rOut, float startAngle,
float sweepAngle, Paint fill, Paint strokeInner, Paint strokeOuter, Paint strokeSides) {
if (sweepAngle > CIRCLE_LIMIT) {
sweepAngle = CIRCLE_LIMIT;
}
if (sweepAngle < -CIRCLE_LIMIT) {
sweepAngle = -CIRCLE_LIMIT;
}

RectF outerRect = new RectF(cx - rOut, cy - rOut, cx + rOut, cy + rOut);
RectF innerRect = new RectF(cx - rInn, cy - rInn, cx + rInn, cy + rInn);

if (fill != null || strokeSides != null) { // to prevent calculating this lot of floats
double start = toRadians(startAngle);
double end = toRadians(startAngle + sweepAngle);
float innerStartX = (float)(cx + rInn * cos(start));
float innerStartY = (float)(cy + rInn * sin(start));
float innerEndX = (float)(cx + rInn * cos(end));
float innerEndY = (float)(cy + rInn * sin(end));
float outerStartX = (float)(cx + rOut * cos(start));
float outerStartY = (float)(cy + rOut * sin(start));
float outerEndX = (float)(cx + rOut * cos(end));
float outerEndY = (float)(cy + rOut * sin(end));
if (fill != null) {
Path segmentPath = new Path();
segmentPath.moveTo(innerStartX, innerStartY);
segmentPath.lineTo(outerStartX, outerStartY);
segmentPath.arcTo(outerRect, startAngle, sweepAngle);
// Path currently at outerEndX,outerEndY
segmentPath.lineTo(innerEndX, innerEndY);
segmentPath.arcTo(innerRect, startAngle + sweepAngle, -sweepAngle); // drawn backwards
canvas.drawPath(segmentPath, fill);
}
if (strokeSides != null) {
canvas.drawLine(innerStartX, innerStartY, outerStartX, outerStartY, strokeSides);
canvas.drawLine(innerEndX, innerEndY, outerEndX, outerEndY, strokeSides);
}
}
if (strokeInner != null) {
canvas.drawArc(innerRect, startAngle, sweepAngle, false, strokeInner);
}
if (strokeOuter != null) {
canvas.drawArc(outerRect, startAngle, sweepAngle, false, strokeOuter);
}
}

How to draw an arc from radius and inner angle in Silverlight

This seems to be a good article on building arcs dynamically http://codingbandit.com/Blog/blog/dynamically-creating-path-data-in-silverlight-2/

To calculate the points the following formula is used.

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

* r is the radius of the circle
* (a,b) is the center of the circle
* (x,y) is the point on the circumference
* θ is the angle in degrees
* radian = degree * π/180

you have the radius of the circle r and also the angle θ. That should build up the point series.

draw rounded edge arc in android with embossed effect

I managed to build the arc some what like below

Sample Image

What I did is I calculated the arc starting and ending point and there I draw the circle with diameter equal to arc thickness.

The code for this is

private void drawSlider(Canvas canvas) {
float sweepDegrees = (value * arcWidthInAngle)
/ (maximumValue - minimumValue);

// the grey empty part of the arc
drawArc(canvas, startAngle, arcWidthInAngle, mTrackColor);

// the colored "filled" part of the arc
drawArc(canvas, startAngle, sweepDegrees, mFillColor);

// the thumb to drag.
int radius = ((diameter/2) - (mArcThickness/2));
Point thumbPoint = calculatePointOnArc(centerX, centerY, radius, startAngle + sweepDegrees);

thumbPoint.x = thumbPoint.x - (mThumbDiameter/2);
thumbPoint.y = thumbPoint.y - (mThumbDiameter/2);

Bitmap thumbBitmap = BitmapFactory.decodeResource(
mContext.getResources(), R.drawable.circle25);

thumbBitmap = getResizedBitmap(thumbBitmap, mThumbDiameter, mThumbDiameter);
canvas.drawBitmap(thumbBitmap, thumbPoint.x, thumbPoint.y,
null);

//drawArc(canvas, startAngle, startAngle + sweepDegrees, white);
}
private void drawArc(Canvas canvas, float startAngle, float sweepDegrees,
Paint paint) {
if (sweepDegrees <= 0 || sweepDegrees > arcWidthInAngle) {
return;
}
path.reset();

int radius = ((diameter/2) - (mArcThickness/2));
Point startPoint = calculatePointOnArc(centerX, centerY, radius, startAngle);
Point endPoint = calculatePointOnArc(centerX, centerY, radius, startAngle + sweepDegrees);

path.arcTo(outerCircle, startAngle, sweepDegrees);
path.arcTo(innerCircle, startAngle + sweepDegrees, -sweepDegrees);
// drawing the circle at both the end point of the arc to git it rounded look.
path.addCircle(startPoint.x, startPoint.y, mArcThickness/2, Path.Direction.CW);
path.addCircle(endPoint.x, endPoint.y, mArcThickness/2, Path.Direction.CW);

path.close();

canvas.drawPath(path, paint);
}
// this is to calculate the end points of the arc
private Point calculatePointOnArc(int circleCeX, int circleCeY, int circleRadius, float endAngle)
{
Point point = new Point();
double endAngleRadian = endAngle * (Math.PI / 180);

int pointX = (int) Math.round((circleCeX + circleRadius * Math.cos(endAngleRadian)));
int pointY = (int) Math.round((circleCeY + circleRadius * Math.sin(endAngleRadian)));

point.x = pointX;
point.y = pointY;

return point;
}
// for the emboss effect set maskfilter of the paint to EmbossMaskFilter
private Paint mTrackColor = new Paint();
MaskFilter mEmboss = new EmbossMaskFilter(new float[] { 0.0f, -1.0f, 0.5f},
0.8f, 15, 1.0f);
mTrackColor.setMaskFilter(mEmboss);

How to draw circle with partitioned in android?

Here's the working code for your requirement....

Editing the code:-

    Paint paint1 = new Paint();
Paint paint2 = new Paint();
Paint paint3 = new Paint();
Paint paint4 = new Paint();
Paint paint5 = new Paint();
final RectF rect = new RectF();
int mRadius = 130;
//Example values
rect.set(getWidth()/2- mRadius, getHeight()/2 - mRadius, getWidth()/2 + mRadius, getHeight()/2 + mRadius);
paint1.setColor(Color.GREEN);
paint1.setStrokeWidth(mRadius/2);
paint1.setAntiAlias(true);
paint1.setStrokeCap(Paint.Cap.BUTT);
paint1.setStyle(Paint.Style.STROKE);
paint2.setColor(Color.RED);
paint2.setStrokeWidth(mRadius/2);
paint2.setAntiAlias(true);
paint2.setStrokeCap(Paint.Cap.BUTT);
paint2.setStyle(Paint.Style.STROKE);
paint3.setColor(Color.BLUE);
paint3.setStrokeWidth(5);
paint3.setAntiAlias(true);
paint3.setStrokeCap(Paint.Cap.BUTT);
paint3.setStyle(Paint.Style.STROKE);
canvas.drawArc(rect, 0, 60, false, paint1);
canvas.drawArc(rect, 60, 60, false, paint2);
canvas.drawArc(rect, 120, 60, false, paint1);
canvas.drawArc(rect, 180, 60, false, paint2);
canvas.drawArc(rect, 240, 60, false, paint1);
canvas.drawArc(rect, 300, 60, false, paint2);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2-mRadius/2, getHeight()/2-mRadius/2,paint3);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2+mRadius/2, getHeight()/2-mRadius/2,paint3);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2-mRadius/2, getHeight()/2+mRadius/2,paint3);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2+mRadius/2, getHeight()/2+mRadius/2,paint3);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2-mRadius/4-mRadius/2, getHeight()/2,paint3);

canvas.drawLine(getWidth()/2,
getHeight()/2, getWidth()/2+mRadius/4+mRadius/2, getHeight()/2,paint3);

paint4.setColor(Color.BLACK);

canvas.drawCircle(getWidth()/2, getHeight()/2, mRadius/2, paint4);

paint5.setColor(Color.YELLOW);
paint5.setStrokeWidth(3);
paint5.setAntiAlias(true);
paint5.setStrokeCap(Paint.Cap.BUTT);
paint5.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getWidth()/2, getHeight()/2, mRadius/2, paint5);

I hope now you satisfy with my answer....



Related Topics



Leave a reply



Submit