Android: looking for a drawArc() method with inner & outer radius

后端 未结 5 1593
逝去的感伤
逝去的感伤 2020-11-29 17:49

I have the following custom view:

\"alt

This I have achieved by using the Canvas\' drawArc

相关标签:
5条回答
  • 2020-11-29 18:12

    You can paint over the inner area using the PorterDuff xfermode called "Clear." This will erase pixels.

    0 讨论(0)
  • 2020-11-29 18:13
    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);
        }
    }
    

    Can be extended to oval arc by duplicating rInn and rOut for x and y directions.

    Also wasn't part of the question, but to draw a text in the middle of a 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);
    
    0 讨论(0)
  • 2020-11-29 18:17

    You can do this:

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

    The key is in paint.setStyle(Paint.Style.STROKE);, it crops the arc's center with the stroke that you define in setStrokeWidth (in the example draws an arc with a radius of mRadius and 20px thick).

    Hope it helps!

    0 讨论(0)
  • 2020-11-29 18:20

    drawing Circle and Arc. the following code is little dirty but it may help

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

    0 讨论(0)
  • 2020-11-29 18:32

    You can try following 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>
    

    0 讨论(0)
提交回复
热议问题