0

I have got this code from another SO question. I was wondering how I could modify it so that the lines connecting the circles and inner circle perimeter have a different color than the outer color peremiter. Say Black color for the outer circle and every other stroke is grey.

private static final float CIRCLE_LIMIT = 359.9999f;
/**
 * 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 canvas
 * @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 &plusmn;360
 * @param fill filling paint, can be <code>null</code>
 * @param stroke stroke paint, 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 stroke) {
    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);

    Path segmentPath = new Path();
    double start = toRadians(startAngle);
    segmentPath.moveTo((float)(cx + rInn * cos(start)), (float)(cy + rInn * sin(start)));
    segmentPath.lineTo((float)(cx + rOut * cos(start)), (float)(cy + rOut * sin(start)));
    segmentPath.arcTo(outerRect, startAngle, sweepAngle);
    double end = toRadians(startAngle + sweepAngle);
    segmentPath.lineTo((float)(cx + rInn * cos(end)), (float)(cy + rInn * sin(end)));
    segmentPath.arcTo(innerRect, startAngle + sweepAngle, -sweepAngle);
    if (fill != null) {
        canvas.drawPath(segmentPath, fill);
    }
    if (stroke != null) {
        canvas.drawPath(segmentPath, stroke);
    }
}

Basically the function parameter would ideally look like:

   public static void drawArcSegment(Canvas canvas, float cx, float cy, float rInn, float rOut, float startAngle, float sweepAngle, Paint fill, Paint strokeOutCircle, Paint StrokeAll) 
Community
  • 1
  • 1
Snake
  • 14,228
  • 27
  • 117
  • 250

2 Answers2

0

set color before paint (ex. before canvas.drawPath(segmentPath, fill);)

ex.

fill.setColor(Color.RED)
stroke.setColor(Color.GREEN)

you can parse Color

Color.parseColor("#FFFFFF")
// -> fill.setColor(Color.parseColor("#FFFFFF"));

or import from resources

getResources().getColor(R.color.mycolor);
// -> fill.setColor(getResources().getColor(R.color.mycolor));
Michał Sułek
  • 278
  • 2
  • 11
  • Please read the question carefully. I am talking about setting color on "Specific" segmants not all of the segments – Snake Jan 09 '15 at 02:17
  • every segment should be another canvas draw in which you setup color, split your code – Michał Sułek Jan 09 '15 at 11:51
  • The code above draws a full path and thus why it is getting stroke color. How would you change the above code to fit the requirements of the question? please feel free to change my code and repost the working one as I know the general idea but I am unable to figure out where the code would have to be changed – Snake Jan 09 '15 at 15:44
0

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 &plusmn;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);
    }
}
TWiStErRob
  • 44,762
  • 26
  • 170
  • 254
  • I figured it out by then. But just to close this question, I accepted the answer. Thanks though – Snake Mar 12 '15 at 17:04