web-dev-qa-db-ja.com

Android:内側と外側の半径を持つdrawArc()メソッドを探す

次のカスタムビューがあります。

alt text

これは、CanvasのdrawArc()メソッドを使用して実現しました。ただし、このdrawArc()メソッドでは、弧の内側の半径を制限できません。

私が欲しいのは次のようなものです:

alt text

外輪だけが残っているところ。

必要なのは、円弧の内側の半径を設定できるdrawArc()関数です。誰でもそれを行う方法を考えていますか?

(ところで、内側の領域をオーバーペイントすることは、透明にする必要があるため機能しません。内側の円をColor.TRANSPARENT赤と青のコーンをペイントした後、古い色が削除されません。それはちょうど別のレイヤーを上に置くだけです、それは透明で、私はまだ赤と青を見ることができます)

34
znq

「クリア」と呼ばれるPorterDuff xfermodeを使用して、内側の領域をペイントできます。これにより、ピクセルが消去されます。

30
Romain Guy

あなたはこれを行うことができます:

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

キーはPaint.setStyle(Paint.Style.STROKE);にあり、setStrokeWidthで定義したストロークでアークの中心をトリミングします(例では、半径がmRadiusで厚さが20pxのアークを描画します)。

それが役に立てば幸い!

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

X方向とy方向にrInnrOutを複製することにより、楕円弧に拡張できます。

また、質問の一部ではありませんでしたが、セグメントの中央にテキストを描画するために:

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

円と弧を描きます。次のコードは少し汚れていますが、役立つかもしれません

        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

次の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