Android: buscando un método drawArc () con radio interior y exterior

Tengo la siguiente vista personalizada:

texto alternativo

Esto lo he logrado utilizando el método drawArc() Canvas. Sin embargo, con este método drawArc() no puedo limitar el radio interno del arco.

Lo que me gustaría tener es algo como esto:

texto alternativo

donde solo queda un anillo exterior.

Lo que necesito es una función drawArc() donde pueda establecer el radio interior del arco. Alguien una idea de cómo hacer eso?

(Por cierto, pintar sobre el área interior no funciona, porque tiene que ser transparente. Pintar un círculo interno con Color.TRANSPARENT después de pintar los conos rojos y azules no elimina el color antiguo. Simplemente pone otra capa encima, que es transparente y a través del cual aún puedo ver el rojo y el azul)

Puede pintar sobre el área interior usando el PorterDuff xfermode llamado “Clear”. Esto borrará los píxeles.

Puedes hacerlo:

  Paint paint = new Paint(); final RectF rect = new RectF(); //Example values rect.set(mWidth/2- mRadius, mHeight/2 - mRadius, mWidth/2 + mRadius, mHeight/2 + mRadius); paint.setColor(Color.GREEN); paint.setStrokeWidth(20); paint.setAntiAlias(true); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStyle(Paint.Style.STROKE); canvas.drawArc(rect, -90, 360, false, paint); 

La clave está en paint.setStyle(Paint.Style.STROKE); , recorta el centro del arco con el trazo que define en setStrokeWidth (en el ejemplo dibuja un arco con un radio de mRadius y 20px de grosor).

¡Espero eso ayude!

 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 * 
 * 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); * 

* 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 ±360 * @param fill filling paint, can be null * @param stroke stroke paint, can be null * @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); } }

Puede extenderse a un arco ovalado duplicando rInn y rOut para las direcciones xey.

Además, no era parte de la pregunta, sino dibujar un texto en el medio de un segmento:

 textPaint.setTextAlign(Align.CENTER); Path midway = new Path(); float r = (rIn + rOut) / 2; RectF segment = new RectF(cx - r, cy - r, cx + r, cy + r); midway.addArc(segment, startAngle, sweepAngle); canvas.drawTextOnPath("label", midway, 0, 0, textPaint); 

Puede intentar siguiendo ShapeDrawable