我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

前言

Android自定义控件经常会用到Canvas绘制2D图形,在优化自己自定义控件技能之前,必须熟练掌握Canvas绘图机制。本文从以下三个方面对Canvas绘图机制进行讲解:

画布Canvas
画笔Paint
示例圆形进度条

画布Canvas

首先,来看一下Android官网对Canvas类的定义:

The Canvas class holds the “draw” calls。To draw something, you need 4 basic components: A Bitmap to hold the pixels, a Canvas to host the draw calls(writing into the bitmap), a drawing primitive(eg, Rect, Path, text, Bitmap), and a paint(to describe the colors and styles for the drawing).

简单来说,Android进行2D绘图必须要有Canvas类的支持,它位于“android.graphics.Canvas”包下。我们可以把Canvas理解成系统分配给我们的一块用于绘图的内存(ps:真正的内存是其包含的Bitmap)。

Canvas提供了两个构造函数:

Canvas() : 创建一个空的Canvas对象。
Canvas(Bitmap bitmap) : 创建一个以bitmap位图为背景的Canvas。
通常,我们会采用第二种包含Bitmap参数的构造函数方式或者直接使用onDraw方法中系统提供的Canvas。

既然Canvas主要用于绘图,那么它提供了很多相应的draw方法,方便我们在Canvas对象上绘图,介绍几个常用的draw方法:

void drawRect(RectF rect, Paint paint) : 绘制区域,参数为RectF的区域。
void drawOval(RectF oval, Paint paint) : 绘制矩形的内切椭圆。
void drawCircle(float cx, float cy, float radius, Paint paint) : 绘制圆形。cx和cy是圆心坐标,radius是半径长度。
void drawArc(RectF oval, float startAngle, float sweepAngle. boolean useCenter, Paint paint) : 绘制圆弧形,也是以矩形的内切椭圆为标准。其中,startAngle为起始角度,sweepAngle为弧度大小,useCenter为true,则是绘制一个扇行,为false,则只是一段圆弧。(ps:startAngle为0时,是圆形钟表3点钟方向)。
void drawPath(Path path, Paint paint) : 根据给定的path,绘制连线。
void drawBitmap(Bitmap bitmap, Rect class="lazy" data-src, Rect dst, Paint paint) : 贴图,参数bitmap是要进行绘制的bitmap对象,参数class="lazy" data-src是指bitmap的源区域(一般为null),dst是bitmap的目标区域,paint是画笔,可为null。
void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) : 根据给定的起点和结束点之间绘制连线。
void drawPoint(float x, float y, Paint paint) : 根据给定的坐标,绘制点。
void drawText(String text, float x, float y, Paint paint) : 根据给定的坐标,绘制文字。其中,x是文本起始的x轴坐标,y是文本纵向结束的y轴坐标。

画笔Paint

从上面列举的几个Canvas.drawXXX()方法可以看到,其中都有一个类型为Paint的参数,可以把它理解成为”画笔”,通过这个画笔,在Canvas这张画布上作画。它位于“android.graphics.Paint”包下,主要用于设置绘图风格,包括画笔颜色。

Paint中提供了大量设置绘画风格的方法,这里仅列出一些常用的功能:

setARGB(int a, int r, int g, int b) : 设置ARGB颜色。
setColor(int color) : 设置颜色。
setAlpha(int a) : 设置透明度。
setAntiAlias(boolean aa) : 设置是否抗锯齿。
setShader(Shader shader) : 设置Paint的填充效果。
setStrokeWidth(float width) : 设置Paint的笔触宽度。
setStyle(Paint.Style style) : 设置Paint的填充风格。
setTextSize(float textSize) : 设置绘制文本时的文字大小。

自定义圆形进度条

这里以一个自定义的圆形进度条为例,我们首先看一下效果图:

通过效果图,我们首先抽象出自定义属性,如下:

圆环内部填充色。
圆环进度条的背景色。
圆环进度条的颜色。
圆环半径。
圆环进度条的宽度。
进度条起始的角度。
中间文字的颜色。
中间文字的大小。
中间文字是否需要显示的标志位。

在Android中,可以在项目的res/values/目录下,建立一个resources源文件,通过declare-styleable来声明一个特定的属性集合。

示例属性集合如下所示(res/values/attrs_round_progress_bar.xml):


<resources>
  <declare-styleable name="RoundProgressBar">
    <attr name="startAngle" format="integer"></attr>
    <attr name="radius" format="dimension"></attr>
    <attr name="ringWidth" format="dimension"></attr>
    <attr name="centerColor" format="color"></attr>
    <attr name="ringColor" format="color"></attr>
    <attr name="progressColor" format="color"></attr>
    <attr name="textSize" format="dimension"></attr>
    <attr name="textColor" format="color"></attr>
    <attr name="isTextDisplay" format="boolean"></attr>
  </declare-styleable>
</resources>

自定义的属性可以在自定义View的构造函数中,通过TypedArray数组获取,我们来自定义一个圆形的View来实现上图的效果(RoundProgressBar.java):


package love.com.progressbar.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import love.com.progressbar.R;
public class RoundProgressBar extends View {
  private static final int START_ANGLE = -90;
  private static final String CENTER_COLOR = "#eeff06";
  private static final String RING_COLOR = "#FF7281E1";
  private static final String PROGRESS_COLOR = "#FFDA0F0F";
  private static final String TEXT_COLOR = "#FF000000";
  private static final int TEXT_SIZE = 30;
  private static final int CIRCLE_RADIUS = 20;
  private static final int RING_WIDTH = 5;
  
  private int startAngle;
  
  private int radius;
  
  private int ringWidth;
  
  private int mProgress = 0;
  
  private int centerColor;
  
  private int ringColor;
  
  private int progressColor;
  
  private int textSize;
  
  private int textColor;
  
  private boolean isTextDisplay;
  private String textContent;
  private Paint mPaint;
  public RoundProgressBar(Context context) {
    this(context, null);
  }
  public RoundProgressBar(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }
  public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    // 获取自定义属性
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);
    for (int i = 0; i < a.length(); i ++) {
      int attr = a.getIndex(i);
      switch (attr) {
        case R.styleable.RoundProgressBar_startAngle:
          startAngle = a.getInteger(attr, START_ANGLE);
          break;
        case R.styleable.RoundProgressBar_centerColor:
          centerColor = a.getColor(attr, Color.parseColor(CENTER_COLOR));
          break;
        case R.styleable.RoundProgressBar_progressColor:
          progressColor = a.getColor(attr, Color.parseColor(PROGRESS_COLOR));
          break;
        case R.styleable.RoundProgressBar_ringColor:
          ringColor = a.getColor(attr, Color.parseColor(RING_COLOR));
          break;
        case R.styleable.RoundProgressBar_textColor:
          textColor = a.getColor(attr, Color.parseColor(TEXT_COLOR));
          break;
        case R.styleable.RoundProgressBar_textSize:
          textSize = (int) a.getDimension(attr, TypedValue.applyDimension(
              TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE,
              getResources().getDisplayMetrics()));
          break;
        case R.styleable.RoundProgressBar_isTextDisplay:
          isTextDisplay = a.getBoolean(attr, true);
          break;
        case R.styleable.RoundProgressBar_radius:
          radius = (int) a.getDimension(attr, TypedValue.applyDimension(
              TypedValue.COMPLEX_UNIT_DIP, CIRCLE_RADIUS,
              getResources().getDisplayMetrics()
          ));
          break;
        case R.styleable.RoundProgressBar_ringWidth:
           ringWidth = (int) a.getDimension(attr, TypedValue.applyDimension(
              TypedValue.COMPLEX_UNIT_DIP, RING_WIDTH,
              getResources().getDisplayMetrics()
          ));
          break;
        default:
          break;
      }
    }
    a.recycle();
    // 初始化画笔设置
    setPaint();
  }
  private void setPaint() {
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
  }
  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 获取圆心坐标
    int cx = getWidth() / 2;
    int cy = cx;
    
    if (centerColor != 0) {
      drawCenterCircle(canvas, cx, cy);
    }
    
    drawOuterCircle(canvas, cx, cy);
    
    drawProgress(canvas, cx, cy);
    
    drawProgressText(canvas, cx, cy);
  }
  private void drawProgressText(Canvas canvas, int cx, int cy) {
    if (!isTextDisplay) {
      return;
    }
    mPaint.setColor(textColor);
    mPaint.setTextSize(textSize);
    mPaint.setTypeface(Typeface.DEFAULT_BOLD);
    mPaint.setStrokeWidth(0);
    textContent = getProgress() + "%";
    float textWidth = mPaint.measureText(textContent);
    canvas.drawText(textContent, cx - textWidth / 2, cy + textSize / 2, mPaint);
  }
  private void drawProgress(Canvas canvas, int cx, int cy) {
    mPaint.setColor(progressColor);
    mPaint.setStrokeWidth(ringWidth);
    mPaint.setStyle(Paint.Style.STROKE);
    RectF mRectF = new RectF(cx - radius, cy - radius, cx + radius, cy + radius);
    float sweepAngle = (float) (mProgress * 360.0 / 100);
    canvas.drawArc(mRectF, startAngle, sweepAngle, false, mPaint);
  }
  private void drawOuterCircle(Canvas canvas, int cx, int cy) {
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setColor(ringColor);
    mPaint.setStrokeWidth(ringWidth);
    canvas.drawCircle(cx, cy, radius, mPaint);
  }
  private void drawCenterCircle(Canvas canvas, int cx, int cy) {
    mPaint.setColor(centerColor);
    mPaint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(cx, cy, radius, mPaint);
  }
  public synchronized int getProgress() {
    return mProgress;
  }
  public synchronized void setProgress(int progress) {
    if (progress < 0) {
      progress = 0;
    } else if (progress > 100) {
      progress = 100;
    }
    mProgress = progress;
    // 进度改变时,需要通过invalidate方法进行重绘
    postInvalidate();
  }
}

在MainActivity.java的布局文件中,可以这样调用圆形进度条:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:round="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <love.com.progressbar.view.RoundProgressBar
    android:id="@+id/id_round_progressbar"
    android:layout_width="400dp"
    android:layout_height="400dp"
    round:radius="100dp"
    round:ringWidth="20dp"
    round:startAngle="-90"
    round:centerColor="#eeff06"
    round:ringColor="#e16556e6"
    round:progressColor="#d20c0c"
    round:textColor="#000000"
    round:textSize="20sp"
    round:isTextDisplay="true"/>
</RelativeLayout>

其中,xmlns:round=”http://schemas.android.com/apk/res-auto是Android Studio中增加的导入自定义View属性的命名空间写法。

您可能感兴趣的文章:Android自定义控件实现带数值和动画的圆形进度条Android编程之ProgressBar圆形进度条颜色设置方法Android三种方式实现ProgressBar自定义圆形进度条Android带进度的圆形进度条自定义Android圆形进度条(附源码)Android自定义漂亮的圆形进度条Android studio圆形进度条 百分数跟随变化Android自定义控件实现圆形进度条Android自定义View之圆形进度条式按钮Android自定义控件实现带文本与数字的圆形进度条


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

前言 Android自定义控件经常会用到Canvas绘制2D图形,在优化自己自定义控件技能之前,必须熟练掌握Canvas绘图机制。本文从以下三个方面对Canvas绘图机制进行讲解: 画布Canvas 画笔Paint 示例圆形进度条画布Can
2022-06-06

android自定义view制作圆形进度条效果

还是我们自定View的那几个步骤: 1、自定义View的属性 2、在View的构造方法中获得我们自定义的属性 [ 3、重写onMesure ] 4、重写onDraw1、自定义属性:2022-06-06

怎么使用Canvas绘制圆形

这篇文章主要介绍“怎么使用Canvas绘制圆形”,在日常操作中,相信很多人在怎么使用Canvas绘制圆形问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么使用Canvas绘制圆形”的疑惑有所帮助!接下来,请跟
2023-06-03

使用Canvas怎么绘制一个未闭合的带进度条圆环

这期内容当中小编将会给大家带来有关使用Canvas怎么绘制一个未闭合的带进度条圆环,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、定义变量定义半径,定义圆环厚度,定义圆心位置、定义默认填充颜色let r
2023-06-09

怎么在Android应用中添加一个圆形进度条效果

这篇文章给大家介绍怎么在Android应用中添加一个圆形进度条效果,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。首先我们在attrs属性文件中增加几个自定义属性2023-05-31

Android绘制圆形百分比加载圈效果

先看一组加载效果图,有点粉粉的加载圈: 自定义这样的圆形加载圈还是比较简单的,主要是用到Canvans的绘制文本,绘制圆和绘制圆弧的api:/** * 绘制圆 * @param cx 圆心x坐标 * @param cy 圆心y坐标
2023-05-30

怎么在Android中自定义一个圆形进度条效果

怎么在Android中自定义一个圆形进度条效果?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android是什么Android是一种基于Linux内核的自由及开放源代码的操作系
2023-06-14

Android编程实现类似于圆形ProgressBar的进度条效果

本文实例讲述了Android编程实现类似于圆形ProgressBar的进度条效果。分享给大家供大家参考,具体如下:我们要实现一个类似于小米分享中的圆形播放进度条,android自带的圆形ProgressBar是默认自动旋转的,所以无法实现,
2022-06-06

使用canvas怎么实现一个圆形进度条动画

这期内容当中小编将会给大家带来有关使用canvas怎么实现一个圆形进度条动画,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. canvas的HTML部分很简单就一个canvas标签canvas画布的宽高
2023-06-09

css怎么实现圆形渐变进度条效果

这篇文章给大家分享的是有关css怎么实现圆形渐变进度条效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。实现思路最外面是一个大圆(渐变色)内部里面绘制两个半圆,将渐变的圆遮住(为了看起来明显,左右两侧颜色不一样,
2023-06-08

HTML5 Canvas怎么实现圆形进度条并显示数字百分比效果

这篇文章主要介绍HTML5 Canvas怎么实现圆形进度条并显示数字百分比效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!实现效果1.首先创建html代码2023-06-09

怎么用Android View实现圆形进度条

本篇内容主要讲解“怎么用Android View实现圆形进度条”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Android View实现圆形进度条”吧!主要涉及到下面几个方法:// 画圆c
2023-06-20

Android自定义View实现圆形加载进度条效果的方法

这篇文章将为大家详细讲解有关Android自定义View实现圆形加载进度条效果的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。View仿华为圆形加载进度条效果图实现思路可以看出该View可分为三个部分
2023-05-30

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录