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技术站