热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要为大家详细介绍了Android绘制圆形百分比加载圈效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

先看一组加载效果图,有点粉粉的加载圈:

这里写图片描述 这里写图片描述

自定义这样的圆形加载圈还是比较简单的,主要是用到Canvans的绘制文本,绘制圆和绘制圆弧的api:

/**
 * 绘制圆
 * @param cx   圆心x坐标
 * @param cy   圆心y坐标
 * @param radius 圆的半径
 * @param paint 画笔
 */
 public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
 ...
 }


/**
 * 绘制圆弧
 * @param oval    决定圆弧范围的矩形区域
 * @param startAngle 开始角度
 * @param sweepAngle 绘制的角度
 * @param useCenter 是否需要连接圆心,true连接,false不连接
 * @param paint   画笔
 */
 public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint) {
  ...
 }


 /**
  * 绘制文本
  * @param text 需要绘制的字符串
  * @param x   绘制文本起点x坐标,注意文本比较特殊,它的起点是左下角的x坐标
  * @param y   绘制文本起点y坐标,同样是左下角的y坐标
  * @param paint 画笔
  */
 public void drawText(String text, float x, float y, Paint paint) {
  ...
 }

开始绘图前需要考虑的以下几点:

1.获取控件的宽和高,这个是决定圆的半径大小的,半径大小等于宽高的最小值的1/2,为什么是最小值呢?因为这样就不会受布局文件中宽高属性不一样的影响,当然我们自己在使用的时候肯定是宽高都是会写成一样的,这样就刚好是一个正方形,绘制出来的圆就刚好在该正方形区域内.做了这样的处理,其他人在用的时候就不用当心圆会不会超出控件范围的情况了.

2.确定圆心的坐标,有了半径和圆心坐标就可以确定一个圆了,布局中的控件区域其实都是一个矩形区域,如果想要绘制出来的圆刚好处于控件的矩形区域内并且和矩形的最短的那条边相切,那么圆心坐标的就是该矩形宽高的1/2,即刚好位于矩形区域的中心点.

3.绘制圆弧,注意这里的圆弧指的是进度圈,看上面的示例图是有2种样式,分别是实心的加载圈和空心加载圈,这个其实就是paint的样式决定,如果是实心圆,paint设置为Paint.Style.FILL(填充模式),同时drawArc的useCenter设置为true;如果是空心圆则paint设置为Paint.Style.STROKE(线性模式),同时drawArc的useCenter设置为false即可.值得一提的是绘制空心圆的时候还需要考虑圆弧的宽度,宽度有多大将决定进度圈的厚度.因此在定义空心圆的矩形区域的时候需要减去进度圈的厚度,否则画出来的进度圈会超出控件的区域.

4.绘制文本,需要定位起始点,文本的起始点比较特殊,它是以左下角为起始点的,起点x坐标=圆心x坐标-文本宽度1/2;起始点y坐标=圆心y坐标+文本高度1/2;至于文本的宽高获取可以通过paint的getTextBounds()方法获取,具体等下看代码.

ok,直接上代码,注释已经很详细了.

圆形加载圈

public class CircleProgressView extends View {
  private int width;//控件宽度
  private int height;//控件高
  private float radius;//半径
  private float pointX;//圆心x坐标
  private float pointY;//圆心y坐标
  private int circleBackgroundColor;//背景颜色
  private int circleBackgroundAlpha; //背景透明度
  private int circleRingColor;//进度颜色
  private int progressTextColor;//进度文本的颜色
  private int progressTextSize;//进度文本的字体大小
  private int circleRingWidth; //进度的宽度
  private Paint mPaint;
  private int progress;//进度值
  private boolean isRingStyle;//是否是空心的圆环进度样式

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

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

  public CircleProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    circleBackgroundColor = Color.WHITE;
    circleRingColor = Color.parseColor("#3A91FF");
    progressTextColor = Color.BLACK;
    circleBackgroundAlpha = 128;
    progressTextSize = 32;
    circleRingWidth = 10;
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setStyle(Paint.Style.FILL);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    width = getMeasuredWidth();
    height = getMeasuredHeight();
    radius = Math.min(width, height) / 2.0f;
    pointX = width / 2.0f;
    pointY = height / 2.0f;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    drawBackground(canvas);
    drawCircleRing(canvas);
    drawProgressText(canvas);
  }

  /**
   * 绘制背景色
   *
   * @param canvas
   */
  private void drawBackground(Canvas canvas) {
    mPaint.setColor(circleBackgroundColor);
    mPaint.setAlpha(circleBackgroundAlpha);
    canvas.drawCircle(pointX, pointY, radius, mPaint);
  }

  /**
   * 绘制圆环
   *
   * @param canvas
   */
  private void drawCircleRing(Canvas canvas) {
    mPaint.setColor(circleRingColor);
    RectF oval = new RectF();
    if (isRingStyle) {
      mPaint.setStyle(Paint.Style.STROKE);
      mPaint.setStrokeWidth(circleRingWidth);
      mPaint.setStrokeCap(Paint.Cap.ROUND);
      //注意:定义圆环的矩形区域是需要考虑圆环的宽度
      oval.left = circleRingWidth / 2.0f;
      oval.top = height / 2.0f - radius + circleRingWidth / 2.0f;
      oval.right = 2 * radius - circleRingWidth / 2.0f;
      oval.bottom = height / 2.0f + radius - circleRingWidth / 2.0f;
      canvas.drawArc(oval, 0, 360 * progress / 100, false, mPaint);
    } else {
      mPaint.setStyle(Paint.Style.FILL);
      oval.left = 0;
      oval.top = height / 2.0f - radius;
      oval.right = 2 * radius;
      oval.bottom = height / 2.0f + radius;
      canvas.drawArc(oval, 0, 360 * progress / 100, true, mPaint);
    }

  }

  /**
   * 绘制进度文本
   *
   * @param canvas
   */
  private void drawProgressText(Canvas canvas) {
    mPaint.setColor(progressTextColor);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setTextSize(progressTextSize);
    Rect textBound = new Rect();
    String text = progress + "%";
    //获取文本的矩形区域到textBound中
    mPaint.getTextBounds(text, 0, text.length(), textBound);
    int textWidth = textBound.width();
    int textHeight = textBound.height();
    float x = pointX - textWidth / 2.0f;
    float y = pointY + textHeight / 2.0f;
    canvas.drawText(text, x, y, mPaint);
  }

  /**
   * 更新进度
   *
   * @param progress
   */
  public void setValue(int progress) {
    this.progress = progress;
    invalidate();
  }

  /**
   * 设置进度圆环的样式
   *
   * @param isRing true是空心的圆环,false表示实心的圆环
   */
  public void setCircleRingStyle(boolean isRing) {
    this.isRingStyle = isRing;
  }

  /**
   * 设置背景透明度
   *
   * @param alpha 0~255
   */
  public void setCircleBackgroundAlpha(int alpha) {
    this.circleBackgroundAlpha = alpha;
  }

  /**
   * 设置进度文本的大小
   * @param progressTextSize
   */
  public void setProgressTextSize(int progressTextSize) {
    this.progressTextSize = progressTextSize;
  }

  /**
   * 设置进度文本的颜色
   * @param progressTextColor
   */
  public void setProgressTextColor(int progressTextColor) {
    this.progressTextColor = progressTextColor;
  }
}

测试类

public class MainActivity extends AppCompatActivity {
  private CircleProgressView mCircleProgressView;
  private int progress;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mCircleProgressView = (CircleProgressView) findViewById(R.id.progressView);
    mCircleProgressView.setCircleRingStyle(false);//实心圆
    HandlerThread thread = new HandlerThread("draw-thread");
    thread.start();
    Handler tHandler = new Handler(thread.getLooper()) {
      @Override
      public void handleMessage(Message msg) {
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
            mCircleProgressView.setValue(progress++);

          }
        });
        if (progress <100) {
          sendEmptyMessageDelayed(0, 100);
        }
      }
    };
    tHandler.sendEmptyMessage(0);
  }
}

XML使用方式

<&#63;xml version="1.0" encoding="utf-8"&#63;>



 



以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • Android 九宫格布局详解及实现:人人网应用示例
    本文深入探讨了人人网Android应用中独特的九宫格布局设计,解析其背后的GridView实现原理,并提供详细的代码示例。这种布局方式不仅美观大方,而且在现代Android应用中较为少见,值得开发者借鉴。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 深入理解 Oracle 存储函数:计算员工年收入
    本文介绍如何使用 Oracle 存储函数查询特定员工的年收入。我们将详细解释存储函数的创建过程,并提供完整的代码示例。 ... [详细]
  • 本文总结了2018年的关键成就,包括职业变动、购车、考取驾照等重要事件,并分享了读书、工作、家庭和朋友方面的感悟。同时,展望2019年,制定了健康、软实力提升和技术学习的具体目标。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • CSS 布局:液态三栏混合宽度布局
    本文介绍了如何使用 CSS 实现液态的三栏布局,其中各栏具有不同的宽度设置。通过调整容器和内容区域的属性,可以实现灵活且响应式的网页设计。 ... [详细]
  • Linux 系统启动故障排除指南:MBR 和 GRUB 问题
    本文详细介绍了 Linux 系统启动过程中常见的 MBR 扇区和 GRUB 引导程序故障及其解决方案,涵盖从备份、模拟故障到恢复的具体步骤。 ... [详细]
  • 本文介绍了如何使用jQuery根据元素的类型(如复选框)和标签名(如段落)来获取DOM对象。这有助于更高效地操作网页中的特定元素。 ... [详细]
  • 本文将详细介绍如何使用剪映应用中的镜像功能,帮助用户轻松实现视频的镜像效果。通过简单的步骤,您可以快速掌握这一实用技巧。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文介绍如何在 Xcode 中使用快捷键和菜单命令对多行代码进行缩进,包括右缩进和左缩进的具体操作方法。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 本文探讨了 RESTful API 和传统接口之间的关键差异,解释了为什么 RESTful API 在设计和实现上具有独特的优势。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
author-avatar
陈柏菱皇君怡惠
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有