Android 一个带圆角的弧形

本文介绍了一个自定义Android视图的实现方法,包括初始化过程、关键属性设置及绘图逻辑。通过Path和Canvas实现了带有圆角的弧形进度条。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class TestView extends View {
    RectF outRectF = new RectF();
    RectF innRectF = new RectF();
    Paint paint;
    Paint paint2;
    private Paint mTrackColor = new Paint();

    Path path;
    public TestView(Context context) {
        this(context, null);
    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        outRectF.left = 30;
        outRectF.right = 630;
        outRectF.top = 30;
        outRectF.bottom = 630;
        innRectF.left = 180;
        innRectF.right = 480;
        innRectF.top = 180;
        innRectF.bottom = 480;
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint2 = new Paint();
        paint2.setAntiAlias(true);
        paint2.setColor(Color.BLACK);
        paint2.setStyle(Paint.Style.STROKE);
        paint2.setStrokeWidth(60);
        paint2.setStrokeCap(Paint.Cap.ROUND);

        MaskFilter mEmboss = new EmbossMaskFilter(new float[] { 0.0f, -1.0f, 0.5f},
                0.8f, 15, 1.0f);
        mTrackColor.setMaskFilter(mEmboss);
        mTrackColor.setColor(0xffff9800);

        path = new Path();
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
    }

    int circleX = 800;
    int circleY = 1200;
    int r = 600;
    int d = 250;
    int round = 15;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(circleX, circleY, r, paint);
        drawArc(canvas, -90, 90f/4f, mTrackColor);
//        canvas.drawArc(outRectF, 180, 40, false, paint2);
    }

    private void drawArc(Canvas canvas, float startAngle, float sweepAngle, Paint paint) {
        path.reset();

        // 计算圆角占得角度
        float angle1 = (float) (Math.sinh(((double) round / 2) / (double) (r - round)) * 2 * 180 / Math.PI);
        float angle2 = (float) (Math.sinh(((double) round / 2) / (double) (r - d + round)) * 2 * 180 / Math.PI);

        // 四个圆角的圆心
        float[] startPoint = calculatePointOnArc(circleX, circleY, r - round, startAngle + angle1);
        float[] endPoint = calculatePointOnArc(circleX, circleY, r - round, startAngle + sweepAngle - angle1);
        float[] startPoint2 = calculatePointOnArc(circleX, circleY, r - d + round, startAngle + angle2);
        float[] endPoint2 = calculatePointOnArc(circleX, circleY, r - d + round, startAngle + sweepAngle - angle2);


        // 画左右边界
        outRectF = getRectF(circleX, circleY, r - round);
        innRectF = getRectF(circleX, circleY, r - d + round);

        path.arcTo(outRectF, startAngle, sweepAngle);
        path.arcTo(innRectF, startAngle + sweepAngle, -sweepAngle);
        path.close();

        outRectF = getRectF(circleX, circleY, r);
        innRectF = getRectF(circleX, circleY, r - d);

        // 画上下圆弧
        path.arcTo(outRectF, startAngle + angle1, sweepAngle - angle1 * 2);
        path.arcTo(innRectF, startAngle + sweepAngle - angle2, -sweepAngle + angle2 * 2);
        // drawing the circle at both the end point of the arc to git it rounded look.
        path.addCircle(startPoint[0], startPoint[1], round, Path.Direction.CW);
        path.addCircle(endPoint[0], endPoint[1], round, Path.Direction.CW);
        path.addCircle(endPoint2[0], endPoint2[1], round, Path.Direction.CW);
        path.addCircle(startPoint2[0], startPoint2[1], round, Path.Direction.CW);

        path.close();
        canvas.drawPath(path, paint);
    }

    RectF getRectF(int circleX, int circleY, int r) {
        RectF rectF = new RectF();
        rectF.left = circleX - r;
        rectF.right = circleX + r;
        rectF.top = circleY - r;
        rectF.bottom = circleY + r;
        return rectF;
    }

    // this is to calculate the end points of the arc
    private float[] calculatePointOnArc(int circleCeX, int circleCeY, int circleRadius, float endAngle)
    {
        float[] point = new float[2];
        double endAngleRadian = endAngle * (Math.PI / 180);

        double pointX = Math.round((circleCeX + circleRadius * Math.cos(endAngleRadian)));
        double pointY = Math.round((circleCeY + circleRadius * Math.sin(endAngleRadian)));

        point[0] = (float) pointX;
        point[1] = (float) pointY;

        return point;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值