web-dev-qa-db-fra.com

Android: recherche d'une méthode drawArc () avec rayon interne et externe

J'ai la vue personnalisée suivante:

alt text

C'est ce que j'ai réalisé en utilisant la méthode Canvas 'drawArc(). Cependant, avec cette méthode drawArc(), je ne peux pas limiter le rayon intérieur de l'arc.

Ce que j'aimerais avoir, c'est quelque chose comme ceci:

alt text

où il ne reste qu'un anneau extérieur.

Ce dont j'ai besoin, c'est d'une fonction drawArc() où je peux définir le rayon intérieur de l'arc. Quelqu'un a une idée de comment faire ça?

(BTW, la peinture de la zone intérieure ne fonctionne pas, car elle doit être transparente. Peindre un cercle intérieur avec Color.TRANSPARENT après avoir peint les cônes rouges et bleus ne supprime pas l'ancienne couleur. Il met juste un autre calque sur le dessus, qui est transparent et à travers lequel je peux toujours voir le rouge et le bleu)

34
znq

Vous pouvez peindre sur la zone intérieure en utilisant le xfermode PorterDuff appelé "Clear". Cela effacera les pixels.

30
Romain Guy

Tu peux le faire:

    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 clé est dans Paint.setStyle(Paint.Style.STROKE);, elle recadre le centre de l'arc avec le trait que vous définissez dans setStrokeWidth (dans l'exemple dessine un arc avec un rayon de mRadius et 20px d'épaisseur).

J'espère que ça aide!

73
Racker
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);
    }
}

Peut être étendu à l'arc ovale en dupliquant rInn et rOut pour les directions x et y.

Ne faisait pas non plus partie de la question, mais pour dessiner un texte au milieu d'un segment:

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);
16
TWiStErRob

dessin Cercle et Arc. le code suivant est peu sale mais cela peut aider

        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;
    }

enter image description here

2
Irfan Ul Haq

Vous pouvez essayer de suivre 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>
2
shailesh