Android: buscando un método drawArc () con radio interior y exterior
-
28-09-2019 - |
Pregunta
Tengo el siguiente vista personalizada:
Esto lo han logrado mediante el método drawArc()
el lienzo. Sin embargo, con este método drawArc()
no puedo limitar radio interior del arco.
Lo que me gustaría tener algo como esto:
donde sólo hay un anillo exterior a la izquierda.
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, Pintabilidad la zona interior no funciona, ya que tiene que ser transparente. Pintura de un círculo interno con Color.TRANSPARENT
después de pintar los conos rojos y azules no elimina el color de edad. Es sólo pone otra capa en la parte superior , que es transparente y a través del cual todavía se puede ver el rojo y azul)
Solución
Se puede pintar sobre el área interna mediante el xfermode PorterDuff llamado "Borrar". Esto borrará píxeles.
Otros consejos
Usted puede hacer esto:
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);
, se recorta el centro del arco con la carrera que defina en setStrokeWidth (en el ejemplo se dibuja un arco con un radio de 20 píxeles y mRadius de espesor).
Hope que ayuda!
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 ±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);
}
}
se puede extender a arco ovalada mediante la duplicación de rInn
y rOut
para direcciones x e y.
Además, no era parte de la pregunta, pero para 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 seguir los siguientes pasos ShapeDrawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="oval" >
<size
android:height="56dp"
android:width="56dp" />
<stroke
android:width="10dp"
android:color="#0000ff" />
</shape>
</item>
<item>
<shape android:shape="oval" >
<size
android:height="24dp"
android:width="25dp" />
<stroke
android:dashGap="10dp"
android:dashWidth="10dp"
android:width="10dp"
android:color="#FF0000" />
</shape>
</item>
dibujo Círculo y Arco. El código siguiente es poco sucio, pero puede ayudar
int sweepAngle sweepAngle = (360/7)%360;
int startAngle = -90;
int x = getWidth()/2;
int y = getHeight()/2;
int radius;
radius = getWidth()/2-50;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(50);
paint.setColor(Color.WHITE);
paint.setColor(Color.parseColor("#CD5C5C"));
mBarPaintFill.setAntiAlias(true);
canvas.drawCircle(x , y , radius, paint);
paint.setColor(Color.BLUE);
for (int i = 1 ; i<=5 ; i++){
canvas.drawArc(x-radius,y-radius,x+radius,y+radius,startAngle,sweepAngle,false,paint);
startAngle = (startAngle + sweepAngle+20)%360;
}