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

yizhihongxing

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日

相关文章

  • Ruby中的block代码块学习教程

    Ruby中的block代码块学习教程 什么是block代码块? 在Ruby中,block代码块是一种被包含在花括号({ })或者do/end关键字中的、可被传递给方法并随后被调用的一段代码集合。 为什么需要block代码块? block代码块有以下两个作用: 可以将一段代码当做一个参数传递给方法; 可以在方法内部定义灵活的逻辑实现,实现代码的可重用性和可扩展…

    other 2023年6月27日
    00
  • 简述php环境搭建与配置

    简述PHP环境搭建与配置 在搭建PHP环境之前需要先明确什么是PHP,它是一种被广泛应用的服务器端脚本语言。PHP常用于编写动态网页脚本并被嵌入HTML中,其代码可以取代完全静态的HTML文件。 环境搭建 1.安装WAMP/MAMP/LAMP(Windows/MacOS/Linux): WAMP(Windows + Apache + MySQL + PHP)…

    other 2023年6月26日
    00
  • Win11用户名和密码怎么备份?Win11用户名和密码方法

    Win11用户名和密码备份攻略 1. Win11用户名和密码的存储位置 Win11的用户名和密码是存储在系统注册表中的。具体路径为:HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\_SC_<SID>\DomainPassword\<UserSID>。 其中,SID是安全标识符,UserSID是用户…

    other 2023年6月27日
    00
  • 【java】对象赋值给另一个对象

    在Java中,对象赋值给另一个对象可以通过引用传递来实现。以下是一个完整攻略,介绍了Java中对象赋值的过程和示例。 步骤1:创建一个Java类 首先我们需要创建一个Java类,用于演示对象赋值的过程。以下是一个示例: public class Person { private String name; private int age; public Per…

    other 2023年5月6日
    00
  • css的!important规则对性能有影响吗

    CSS的!important规则对性能有影响吗? CSS的!important规则是用来覆盖其他样式规则的,它可以强制使某个样式生效,即使这个样式的优先级比其他样式低。但是,使用!important规则可能会对性能产生一定的影响。本文将详细讲解!important规则对性能的影响,并提供一些优化建议。 !important规则的影响 使用!important…

    other 2023年5月5日
    00
  • 像素 分辨率 ppi(像素密度) bpp扫盲

    像素 分辨率 ppi(像素密度) bpp扫盲 什么是像素? 像素(Pixel)是图像图形处理中最小的显示单位。像素可以是数字或者光学系统中的单个光点。在数字图像处理中,像素是计算机中显示图像的基本单位,在显示器或打印机中,一个像素被视为一个独立的圆点。 什么是分辨率? 分辨率(Resolution)是指显示器或打印机中的像素数目。通常,分辨率以水平像素数×垂…

    其他 2023年3月29日
    00
  • Xmind8 Pro 最新激活序列号

    Xmind8 Pro 最新激活序列号攻略 1. 确认Xmind8 Pro版本 在进行激活序列号之前,首先需要确认当前安装的Xmind8 Pro版本。可以在软件界面的左上角找到“Xmind8”菜单,点击下拉菜单中的“关于Xmind8”,弹出的窗口中会显示当前版本信息。请确保下载的序列号与当前版本匹配。 示例说明:如果当前安装的Xmind8版本为3.7.6,则需…

    other 2023年6月27日
    00
  • matlab对于文本文件(txt)数据读取的技巧总结(经典中的经典)

    Matlab对于文本文件(txt)数据读取的技巧总结(经典中的经典) 在数据处理的过程中,文本文件是最为常见和基础的数据类型之一,而对于文本文件的读取处理在各种科学研究、工程实践以及金融数据分析等领域都有极其广泛的应用。本文将基于Matlab平台,从几个重要的方面总结和介绍文本文件读取的技巧。 一、读取文本文件的函数-textread(textscan) M…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部