Android使用Canvas绘制圆形进度条效果

Android使用Canvas绘制圆形进度条效果

简介

在Android开发中,我们时常需要实现进度条效果。目前Android SDK中提供了ProgressBar和SeekBar两个基础进度条控件,但是它们的样式比较单一,难以满足特定的设计需求。因此,针对特定的UI设计需求,我们需要自定义进度条控件。其中,绘制圆形进度条是比较常用的一种方式。

本篇教程将基于Android平台,使用Canvas绘制圆形进度条效果。下面将为您详细介绍具体实现过程。

实现步骤

步骤一:绘制圆弧

在Layout布局文件中,添加一个自定义View,并在View的构造方法中初始化Paint和RectF对象。

public class CircleProgressBarView extends View {

    private Paint mPaint;
    private RectF mRectF;

    public CircleProgressBarView(Context context) {
        this(context, null);
    }

    public CircleProgressBarView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleProgressBarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initPaint();
        initRectF();
    }

    /**
     * 初始化Paint
     */
    private void initPaint() {
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE); // 空心
        mPaint.setAntiAlias(true); // 抗锯齿
        mPaint.setStrokeWidth(10); // 宽度
        mPaint.setColor(Color.GREEN); // 颜色
    }

    /**
     * 初始化RectF
     */
    private void initRectF() {
        mRectF = new RectF(100, 100, 500, 500); // 定义绘制的矩形区域
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawArc(mRectF, -90, 260, false, mPaint); // 绘制圆弧
    }
}

在onDraw()方法中使用canvas对象的drawArc()方法绘制一个圆弧。参数说明如下:

  • RectF:定义弧线所使用的矩形区域。
  • startAngle:开始角度,-90表示12点钟方向。
  • sweepAngle:扫过的角度,这里为260度,即围绕圆心旋转260度,刚好覆盖整个View的60%。
  • useCenter:是否连接圆心。

运行程序,可以看到一个绿色的圆弧图形已经绘制完成。

步骤二:绘制进度颜色效果

在Step1的基础上,我们需要实现一个从0到100%的进度动画效果。

首先,我们需要定义一个变量mProgress(0~100),用来控制进度条绘制的百分比。然后,在onDraw()方法中计算当前需要绘制的圆弧的角度:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    float sweepAngle = mProgress / 100f * 260f; // 计算当前需要绘制的圆弧角度
    canvas.drawArc(mRectF, -90, sweepAngle, false, mPaint); // 绘制圆弧
}

其中,-90表示顺时针旋转,sweepAngle是当前进度百分比所对应的角度。

我们还需要添加一些属性和方法来控制进度条的动画效果:

public class CircleProgressBarView extends View {

    private int mMax = 100; // 最大进度值
    private int mProgress = 0; // 当前进度值
    private int mDuration = 200; // 动画时长,单位毫秒
    private boolean mIsAnimationEnabled = true; // 是否开启动画效果
    private long mStartTime; // 动画开始时间

    /**
     * 设置最大进度
     */
    public void setMax(int max) {
        mMax = max;
    }

    /**
     * 设置当前进度
     */
    public void setProgress(int progress) {
        if (mProgress != progress && progress >= 0 && progress <= mMax) {
            if (mIsAnimationEnabled) {
                mStartTime = System.currentTimeMillis();
                postInvalidateOnAnimation(); // 异步刷新View
            } else {
                mProgress = progress;
                invalidate();
            }
        }
    }

    /**
     * 获取当前进度
     */
    public int getProgress() {
        return mProgress;
    }

    /**
     * 开启/关闭动画效果
     */
    public void setAnimationEnabled(boolean enabled) {
        this.mIsAnimationEnabled = enabled;
    }

    // 省略部分代码...
}

在setProgress()方法中,我们检查参数值是否合法,如果参数值没有变化,或者不在0~100范围内,那么不做任何操作,否则开始绘制进度条。

如果开启了动画效果,则我们使用postInvalidateOnAnimation()方法来实现动画效果。这是Android的一种优化方式,会启动一个异步线程,在下一帧时刷新View。

我们修改一下onDraw()方法的代码:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    float sweepAngle;
    if (mIsAnimationEnabled) {
        float progress = Math.min((System.currentTimeMillis() - mStartTime) / (float) mDuration, 1.0f);
        sweepAngle = progress * mProgress / 100f * 260f;
    } else {
        sweepAngle = mProgress / 100f * 260f;
    }
    canvas.drawArc(mRectF, -90, sweepAngle, false, mPaint); // 绘制圆弧
    if (mIsAnimationEnabled && mProgress != 0 && mProgress != 100) {
        postInvalidateOnAnimation();
    }
}

我们添加了一个新的判断语句,如果mIsAnimationEnabled为true,那么计算当前进度所对应的值,然后重新绘制圆弧。

在这个判断语句的末尾,如果进度条未达到最大或最小值,那么我们继续启动异步线程进行下一帧刷新。

这就是整个绘制圆形进度条的过程,下面有两个示例说明:

Step1 示例

以下代码演示的是最基本的绘制圆弧效果。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CircleProgressBarView progressBarView = findViewById(R.id.progress_bar_view);
    }
}

在activity_main.xml文件中,添加一个自定义View:

<com.example.circleprogressbar.view.CircleProgressBarView
    android:id="@+id/progress_bar_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

在布局文件中,我们只是添加了一个自定义View,并指定了宽高属性,不做任何其他设置。运行程序,可以看到一个绿色的圆弧图形已经绘制完成。

Step2 示例

以下代码演示的是一个从0到100%的进度动画效果。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        CircleProgressBarView progressBarView = findViewById(R.id.progress_bar_view);
        progressBarView.setMax(100);
        progressBarView.setProgress(0);
        progressBarView.setAnimationEnabled(true);

        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                progressBarView.setProgress(40);
            }
        }, 1000);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                progressBarView.setProgress(80);
            }
        }, 2000);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                progressBarView.setProgress(100);
            }
        }, 3000);
    }
}

在这个示例中,我们添加了一些交互代码。首先,我们在onCreate()方法中获取自定义View的实例,并设置最大进度为100,开始进度为0,开启动画效果。

然后,我们使用了Handler对象来模拟进度条的动画效果。在1000、2000、3000毫秒的时刻,我们通过setProgress()方法依次设置进度为40、80、100。每次设置进度后,程序会自动刷新View,从而实现了一个从0~100%的进度动画效果。

可以在自己的项目中参考以上两个示例进行修改,以满足自己的需求。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android使用Canvas绘制圆形进度条效果 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • 华为通过adb取消系统更新

    华为通过adb取消系统更新攻略 在华为手机上,我们可以通过adb命令来取消系统更新。本攻略将详细介绍如何通过adb取消华手机的系统更新,并提供两个示例说明。 准备工作 在操作之前,需要先准备好以下工作: 安装adb驱动程序,可以从官方网站(https://developer.android.com/studio/releases/platform-tools…

    other 2023年5月7日
    00
  • Typescript 封装 Axios拦截器方法实例

    请看下面的详细讲解。 Typescript 封装 Axios拦截器方法实例 本文将介绍如何使用 Typescript 封装 Axios 拦截器方法,让 Axios 在实际使用过程中具备更好的扩展性和可维护性。 为什么需要封装 Axios 拦截器方法? Axios 是一个功能强大、易于使用的 HTTP 请求库,但在实际使用过程中,我们经常会遇到一些通用的问题,…

    other 2023年6月25日
    00
  • js中的数组Array定义与sort方法使用示例

    下面是关于JS中数组定义与sort方法的完整攻略: 数组定义 JS中的数组是一种特殊的变量,可以同时存储多个值。以下是几种常见的数组定义方式: 1. 直接定义 直接使用方括号[]定义一个数组,其中每个元素用逗号分隔。 var arr = [‘apple’, ‘banana’, ‘orange’]; 2. 使用Array构造函数 使用Array()构造函数创建…

    other 2023年6月25日
    00
  • linux命令之rpm安装命令

    Linux命令之rpm安装命令 在Linux系统中,我们可以使用rpm命令来安装、升级和卸载RPM包。RPM包是一种常见的软件包,它包含了软件的二进制文件、配置文件、文档等内容。本攻略将详介绍rpm命令的使用方法,包基本概念、安装配置和示例说明。 基本概念 RPM(Red Hat Package Manager)是一种常见的软件包格式它包含了软件的二进制文件…

    other 2023年5月6日
    00
  • oracle数据库之rownum和rowid用法

    以下是详细讲解“Oracle数据库之ROWNUM和ROWID用法的完整攻略,过程中至少包含两条示例说明”的标准Markdown格式文本: Oracle数据库之ROWNUM和ROWID用法 在Oracle数据库中,ROWNUM和ROWID是两个常用的关键字,用于查询和操作表中的数据。以下是ROWNUM和ROWID的详细介绍和用法。 ROWNUM ROWNUM是…

    other 2023年5月10日
    00
  • bak是什么文件 怎么打开 打开bak文件的图文步骤

    bak是什么文件? .bak文件是一种备份文件,通常用于存储原始文件的副本。当你编辑或修改一个文件时,有时会创建一个.bak文件,以便在需要时可以恢复到原始版本。.bak文件通常与原始文件位于同一目录中,并具有相同的文件名,只是扩展名不同。 如何打开.bak文件? 要打开.bak文件,你可以按照以下步骤进行操作: 确认文件类型:首先,你需要确认.bak文件的…

    other 2023年8月6日
    00
  • php从完整文件路径中分离文件目录和文件名的方法

    分离文件目录和文件名通常是在处理文件操作时经常会用到的操作。在PHP中,我们可以使用函数pathinfo()和dirname()来实现分离文件目录和文件名。下面是详细的攻略: 使用pathinfo() pathinfo() 函数返回文件路径的信息,包括文件目录、文件名、文件扩展名等信息。我们可以利用它来获取文件名称、文件目录和文件扩展名信息。 下面是一个示例…

    other 2023年6月26日
    00
  • android 关于利用签名的SHA1进行安全校验的方法之一(推荐)

    以下是利用签名的SHA1进行安全校验的方法之一的完整攻略: Android应用签名和SHA1获取 生成签名文件:使用Android Studio生成应用的签名文件(.jks或.keystore文件)。可以通过以下步骤生成签名文件: 打开Android Studio,选择“Build”菜单,然后选择“Generate Signed Bundle/APK”。 选…

    other 2023年10月14日
    00
合作推广
合作推广
分享本页
返回顶部