Android自定义圆形百分比加载圈实现

0 下载量 83 浏览量 更新于2024-09-02 收藏 108KB PDF 举报
"Android开发中实现圆形百分比加载圈效果的方法和步骤,涉及Canvas的drawCircle、drawArc和drawText等关键API的使用,以及在实际应用中的注意事项。" 在Android开发中,创建一个自定义的圆形百分比加载圈可以提升用户界面的交互体验。下面我们将详细探讨如何实现这一功能,以及在实现过程中需要注意的关键点。 首先,我们要用到的核心组件是`Canvas`,它提供了在屏幕上绘制图形的能力。`Canvas`提供了多个方法来绘制各种形状,如`drawCircle`用于绘制圆形,`drawArc`用于绘制圆弧,以及`drawText`用于绘制文本。这些方法都是我们在创建百分比加载圈时必不可少的工具。 1. **绘制圆** - `drawCircle(float cx, float cy, float radius, @NonNull Paint paint)`:这个方法接收圆心的坐标(cx, cy)和半径(radius),以及一个`Paint`对象,用于定义颜色和风格。通过这个方法,我们可以创建一个完整的圆形。 2. **绘制圆弧** - `drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)`:`RectF oval`参数是决定圆弧范围的矩形,`startAngle`和`sweepAngle`分别代表圆弧的起始角度和扫过的角度,`useCenter`参数决定是否连接圆心。通过调整这些参数,我们可以绘制出百分比加载圈的动态效果。 3. **绘制文本** - `drawText(String text, float x, float y, Paint paint)`:这个方法用于在指定位置(x, y)绘制文本,这里的文本通常是百分比值。需要注意的是,文本的基线位于坐标(x, y),而非顶部或中心。 在开始绘制之前,我们需要考虑以下几个关键点: 1. **确定圆的尺寸**:根据控件的宽度和高度,我们通常将半径设置为最小值的一半,以确保圆形不会超出控件的边界。这样,无论控件的宽度和高度如何变化,圆形始终能在其中居中显示。 2. **计算圆心坐标**:圆心坐标应该是控件区域的中心点,即宽度和高度除以2,确保圆与控件边缘相切。 3. **百分比计算**:我们需要根据加载进度来计算圆弧的实际扫过角度,从而实现动态的加载效果。这通常涉及到一个转换过程,即将百分比转换为对应的弧度。 4. **动画效果**:为了使加载圈更生动,我们可以使用`ValueAnimator`或者`ObjectAnimator`来平滑地改变圆弧的`sweepAngle`,从而模拟加载过程。 5. **颜色和样式**:`Paint`对象可以用来设置线条颜色、填充颜色、线条宽度等,以满足设计需求。例如,这里提到的“粉粉的加载圈”可以通过设置`Paint`的颜色来实现。 6. **重绘机制**:当百分比发生变化时,我们需要调用`View`的`invalidate()`方法来触发重绘,让UI实时更新。 创建一个Android的圆形百分比加载圈涉及到对`Canvas` API的熟练掌握,以及对UI设计原理的理解。通过合理利用这些工具和技巧,我们可以构建出既美观又实用的加载指示器。在实际开发中,还需要考虑到性能优化和不同设备的适配问题,以确保在各种环境下都能流畅运行。
2014-12-31 上传
总共分为三层:一层为圆形边线,一层为进度边线,一层用来显示标识进度节点。 public class CircleProgressBar extends View { private int maxProgress = 100; private int progress = 15; private int progressStrokeWidth = 2; private int marxArcStorkeWidth = 16; // 画圆所在的距形区域 RectF oval; Paint paint; public CircleProgressBar(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub oval = new RectF(); paint = new Paint(); } @Override protected void onDraw(Canvas canvas) { // TODO 自动生成的方法存根 super.onDraw(canvas); int width = this.getWidth(); int height = this.getHeight(); width = (width > height) ? height : width; height = (width > height) ? height : width; paint.setAntiAlias(true); // 设置画笔为抗锯齿 paint.setColor(Color.WHITE); // 设置画笔颜色 canvas.drawColor(Color.TRANSPARENT); // 白色背景 paint.setStrokeWidth(progressStrokeWidth); // 线宽 paint.setStyle(Style.STROKE); oval.left = marxArcStorkeWidth / 2; // 左上角x oval.top = marxArcStorkeWidth / 2; // 左上角y oval.right = width - marxArcStorkeWidth / 2; // 左下角x oval.bottom = height - marxArcStorkeWidth / 2; // 右下角y canvas.drawArc(oval, -90, 360, false, paint); // 绘制白色圆圈,即进度条背景 paint.setColor(Color.rgb(0x57, 0x87, 0xb6)); paint.setStrokeWidth(marxArcStorkeWidth); canvas.drawArc(oval, -90, ((float) progress / maxProgress) * 360, false, paint); // 绘制进度圆弧,这里是蓝色 paint.setStrokeWidth(1); String text = progress + "%"; int textHeight = height / 4; paint.setTextSize(textHeight); int textWidth = (int) paint.measureText(text, 0, text.length()); paint.setStyle(Style.FILL); canvas.drawText(text, width / 2 - textWidth / 2, height / 2 + textHeight / 2, paint); } public int getMaxProgress() { return maxProgress; } public void setMaxProgress(int maxProgress) { this.maxProgress = maxProgress; } /** * 设置进度 * * @param progress * 进度百分比 * @param view * 标识进度的节点视图 */ public void setProgress(int progress, View view) { this.progress = progress; view.setAnimation(pointRotationAnima(0, (int) (((float) 360 / maxProgress) * progress))); this.invalidate(); } /** * 非UI线程调用 */ public void setProgressNotInUiThread(int progress, View view) { this.progress = progress; view.setAnimation(pointRotationAnima(0, (int) (((float) 360 / maxProgress) * progress))); this.postInvalidate(); } /** * 进度标注点的动画 * * @param fromDegrees * @param toDegrees * @return */ private Animation pointRotationAnima(float fromDegrees, float toDegrees) { int initDegress = 306;// 进度点起始位置(图片偏移约54度) RotateAnimation animation = new RotateAnimation(fromDegrees, initDegress + toDegrees, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); animation.setDuration(1);// 设置动画执行时间 animation.setRepeatCount(1);// 设置重复执行次数 animation.setFillAfter(true);// 设置动画结束后是否停留在结束位置 return animation; } }