欢迎访问宙启技术站
智能推送

android实现圆形渐变进度条

发布时间:2023-05-18 19:16:54

圆形渐变进度条是一种非常美观的进度条效果,可以在很多场合中使用,比如APP中的下载进度条、音乐播放器中的播放进度条等等。本文将介绍如何实现一个圆形渐变进度条,主要包含以下几个方面的内容:

1. 实现原理

圆形渐变进度条的实现原理比较简单,主要是使用Android自带的Canvas绘制功能来绘制一个圆形,并使用渐变色来实现进度条的渐变效果。具体实现步骤如下:

1)创建一个自定义View,并重写onDraw()方法,在该方法中使用Canvas绘制一个圆形;

2)创建一个Paint对象,设置为渐变色,并使用渐变色来绘制进度条;

3)在进度条的位置上绘制一个小圆点,以增强进度条的可读性。

2. 具体实现

2.1 创建自定义View

在创建自定义View之前,需要明确View的大小和样式。本文以500px的圆形进度条为例,大小可以根据实际需求进行调整,样式如下图所示:

![image.png](https://cdn.nlark.com/yuque/0/2022/png/97322/1641940747313-11af7e12-3b5e-423a-8a5e-12460b9e1d85.png#clientId=ubd74b435-27fa-4&from=paste&id=ucb5a69ab&margin=%5Bobject%20Object%5D&originHeight=606&originWidth=600&originalType=binary&ratio=1&status=done&style=none&taskId=u51100671-aa20-4c08-9e2b-719ba7c0f82)

创建自定义View的代码如下:

public class CircleProgressBar extends View {

    private Paint mPaint;
    private int mProgress; // 进度
    private int mMaxProgress = 100; // 最大进度

    public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public CircleProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CircleProgressBar(Context context) {
        super(context);
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true); // 抗锯齿
        mPaint.setStyle(Paint.Style.STROKE); // 描边
        mPaint.setStrokeCap(Paint.Cap.ROUND); // 圆角笔触
        mPaint.setStrokeWidth(20); // 描边宽度
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int size = Math.min(width, height);
        setMeasuredDimension(size, size);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int centerX = getWidth() / 2;
        int centerY = getHeight() / 2;
        int radius = getWidth() / 2 - 30;
        // 绘制灰色圆形
        mPaint.setColor(0xffe0e0e0);
        canvas.drawCircle(centerX, centerY, radius, mPaint);
        // 绘制进度条
        float sweepAngle = mProgress * 1.0f / mMaxProgress * 360;
        // 创建渐变色
        int[] colors = {0xffFFD700, 0xffFFA500, 0xffFF6347};
        float[] positions = {0.2f, 0.5f, 0.8f};
        SweepGradient gradient = new SweepGradient(centerX, centerY, colors, positions);
        mPaint.setShader(gradient);
        canvas.drawArc(new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius), -90, sweepAngle, false, mPaint);
        // 绘制进度条上的小圆点
        double radians = Math.PI * (sweepAngle - 90) / 180;
        float x = centerX + (float) (radius * Math.cos(radians));
        float y = centerY + (float) (radius * Math.sin(radians));
        mPaint.setShader(null);
        mPaint.setColor(0xffFFD700);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(x, y, 10, mPaint);
    }

    public int getProgress() {
        return mProgress;
    }

    public void setProgress(int progress) {
        if (progress < 0) {
            progress = 0;
        } else if (progress > mMaxProgress) {
            progress = mMaxProgress;
        }
        mProgress = progress;
        invalidate();
    }

    public int getMaxProgress() {
        return mMaxProgress;
    }

    public void setMaxProgress(int maxProgress) {
        mMaxProgress = maxProgress;
    }
}

2.2 设置渐变色

在onDraw()方法中,使用SweepGradient来创建渐变色。SweepGradient是一个环形渐变色,需要指定渐变的位置和颜色,代码如下:

int[] colors = {0xffFFD700, 0xffFFA500, 0xffFF6347};
float[] positions = {0.2f, 0.5f, 0.8f};
SweepGradient gradient = new SweepGradient(centerX, centerY, colors, positions);
mPaint.setShader(gradient);

其中,colors为颜色数组,positions为颜色的位置,范围在0-1之间,表示每种颜色从哪个位置开始出现。在上面的代码中,颜色从0.2f、0.5f、0.8f这三个位置开始出现,对应的颜色分别是黄色、橙色、红色,如下图所示:

![image.png](https://cdn.nlark.com/yuque/0/2022/png/97322/1641940771070-10d5f588-16df-40fd-a9a4-67c2ea692fed.png#clientId=ubd74b435-27fa-4&from=paste&id=u97d046bc&margin=%5Bobject%20Object%5D&originHeight=276&originWidth=630&originalType=binary&ratio=1&status=done&style=none&taskId=u78ce6174-88c6-4b74-9f4b-2b203673388)

2.3 绘制小圆点

在进度条的末端绘制一个小圆点可以增强进度条的可读性,可以使用数学公式计算出圆点的位置,代码如下:

double radians = Math.PI * (sweepAngle - 90) / 180;
float x = centerX + (float) (radius * Math.cos(radians));
float y = centerY + (float) (radius * Math.sin(radians));
canvas.drawCircle(x, y, 10, mPaint);

其中,radians为进度条末端的角度,x和y分别为小圆点的横坐标和纵坐标,最后使用canvas.drawCircle()方法在指定位置绘制小圆点。

3. 使用方法

将以上代码保存在一个CircleProgressBar.java文件中,然后在布局文件中引用该View即可使用,如下所示:

<com.example.demo.CircleProgressBar
    android:id="@+id/progress_bar"
    android:layout_width="500dp"
    android:layout_height="500dp"
    android:layout_gravity="center"
    app:maxProgress="100"
    app:progress="0" />

在Java代码中可以使用以下方法来设置进度条的进度:

CircleProgressBar progressBar = findViewById(R.id.progress_bar);
progressBar.setProgress(50);

最终效果如下图所示:

![image.png](https://cdn.nlark.com/yuque/0/2022/png/97322/1641940808331-a2383e06-13e1-4b5e-bcfe-a8e878b6f62b.png#clientId=ubd74b435-27fa-4&from=paste&id=u05bac6c7&margin=%5Bobject%20