Android 自定义圆形带刻度渐变色的进度条样式实例代码

效果图

一、绘制圆环

圆环故名思意,第一个首先绘制是圆环

1:圆环绘制函数

圆环API

public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

参数说明

oval:圆弧所在的椭圆对象。

startAngle:圆弧的起始角度。

sweepAngle:圆弧的角度。

useCenter:是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示。

paint:绘制时所使用的画笔。

 //circleCenter 整个圆半径 radius圆环的半径
RectF oval = new RectF(circleCenter - radius, circleCenter - radius, circleCenter + radius, circleCenter + radius);
//因为-90°才是从12点钟方向开始 所以从-90开始 progress 为进度
canvas.drawArc(oval, -90, (float) (progress * 3.6), false, paint);

2:对圆环上色

因为要的是渐变效果API也有提供

函数名是:SweepGradient

构造函数

public SweepGradient (float cx, float cy, int[] colors, float[] positions)

cx  渲染中心点x 坐标

cy  渲染中心y 点坐标

colors  围绕中心渲染的颜色数组,至少要有两种颜色值

positions   相对位置的 颜色 数组 ,可为null,  若为null,可为null, 颜色 沿渐变线 均匀分布

public SweepGradient (float cx, float cy, int color0, int color1)

cx  渲染中心点x 坐标

cy  渲染中心点y 坐标

color0  起始渲染颜色

color1  结束渲染颜色

实现样式

//渐变颜色 你可以添加很多种但是至少要保持在2种颜色以上
int[] colors = {0xffff4639, 0xffCDD513, 0xff3CDF5F};
 //circleWidth 圆的直径 取中心点
 SweepGradient sweepGradient = new SweepGradient(this.circleWidth / 2, this.circleWidth / 2, colors, null);

但是最后实现出来的效果是渐变开始角度是从0°开始的 但是我们想要的要求是从-90°开始 因此需要对绘制的圆环进行旋转

 //旋转 不然是从0度开始渐变
 Matrix matrix = new Matrix();
 matrix.setRotate(-90, this.circleWidth / 2, this.circleWidth / 2);
 sweepGradient.setLocalMatrix(matrix);

最后将渐变添加到圆环

paint.setShader(sweepGradient);

因为是需要保持第一个圆环的采用渐变,所以在绘制时候在利用完之后 将设置

paint.setShader(null);

3:绘制剩余的进度

一样的是绘制圆环开始角度

//同样的因为是反向绘制的 也可以根据当前的有颜色的角度结束角度开始绘制到-90°
 canvas.drawArc(oval, -90, (float) (-(100 - progress) * 3.6), false, paint);

最终实现效果如图1所示

二、刻度

1:圆环刻度

是对整个圆环根据刻度大小进行平分,计算出每个所占的角度 然后根据当前的进度计算该显示几个圆环之后再绘制上去,刻度使用是也是圆环,只是角度很小而已

如下

 float start = -90f;
   float p = ((float) maxColorNumber / (float) 100);
   p = (int) (progress * p);
   for (int i = 0; i < p; i++) {
    paint.setColor(roundBackgroundColor);
    // 绘制间隔快
    canvas.drawArc(oval, start + singlPoint - lineWidth, lineWidth, false,     paint);
    start = (start + singlPoint);
   }

2:文字刻度

也就是绘制文字是对文字绘制之后进行相应的旋转

 //绘制文字刻度
  for (int i = 1; i <= 10; i++) {
   canvas.save();// 保存当前画布
   canvas.rotate(360 / 10 * i, circleCenter, circleCenter);
   canvas.drawText(i * 10 + "", circleCenter, circleCenter - radius + roundWidth / 2 + getDpValue(4) + textSize, mPaintText);
   canvas.restore();//
  }

最后上整个View代码

package com.example.shall.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class CircularRingPercentageView extends View {
 private Paint paint;
 private int circleWidth;
 private int roundBackgroundColor;
 private int textColor;
 private float textSize;
 private float roundWidth;
 private float progress = 0;
 private int[] colors = {0xffff4639, 0xffCDD513, 0xff3CDF5F};
 private int radius;
 private RectF oval;
 private Paint mPaintText;
 private int maxColorNumber = 100;
 private float singlPoint = 9;
 private float lineWidth = 0.3f;
 private int circleCenter;
 private SweepGradient sweepGradient;
 private boolean isLine;
 /**
  * 分割的数量
  *
  * @param maxColorNumber 数量
  */
 public void setMaxColorNumber(int maxColorNumber) {
  this.maxColorNumber = maxColorNumber;
  singlPoint = (float) 360 / (float) maxColorNumber;
  invalidate();
 }
 /**
  * 是否是线条
  *
  * @param line true 是 false否
  */
 public void setLine(boolean line) {
  isLine = line;
  invalidate();
 }
 public int getCircleWidth() {
  return circleWidth;
 }
 public CircularRingPercentageView(Context context) {
  this(context, null);
 }
 public CircularRingPercentageView(Context context, AttributeSet attrs) {
  this(context, attrs, 0);
 }
 public CircularRingPercentageView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircularRing);
  maxColorNumber = mTypedArray.getInt(R.styleable.CircularRing_circleNumber, 40);
  circleWidth = mTypedArray.getDimensionPixelOffset(R.styleable.CircularRing_circleWidth, getDpValue(180));
  roundBackgroundColor = mTypedArray.getColor(R.styleable.CircularRing_roundColor, 0xffdddddd);
  textColor = mTypedArray.getColor(R.styleable.CircularRing_circleTextColor, 0xff999999);
  roundWidth = mTypedArray.getDimension(R.styleable.CircularRing_circleRoundWidth, 40);
  textSize = mTypedArray.getDimension(R.styleable.CircularRing_circleTextSize, getDpValue(8));
  colors[0] = mTypedArray.getColor(R.styleable.CircularRing_circleColor1, 0xffff4639);
  colors[1] = mTypedArray.getColor(R.styleable.CircularRing_circleColor2, 0xffcdd513);
  colors[2] = mTypedArray.getColor(R.styleable.CircularRing_circleColor3, 0xff3cdf5f);
  initView();
  mTypedArray.recycle();
 }
 /**
  * 空白出颜色背景
  *
  * @param roundBackgroundColor
  */
 public void setRoundBackgroundColor(int roundBackgroundColor) {
  this.roundBackgroundColor = roundBackgroundColor;
  paint.setColor(roundBackgroundColor);
  invalidate();
 }
 /**
  * 刻度字体颜色
  *
  * @param textColor
  */
 public void setTextColor(int textColor) {
  this.textColor = textColor;
  mPaintText.setColor(textColor);
  invalidate();
 }
 /**
  * 刻度字体大小
  *
  * @param textSize
  */
 public void setTextSize(float textSize) {
  this.textSize = textSize;
  mPaintText.setTextSize(textSize);
  invalidate();
 }
 /**
  * 渐变颜色
  *
  * @param colors
  */
 public void setColors(int[] colors) {
  if (colors.length < 2) {
   throw new IllegalArgumentException("colors length < 2");
  }
  this.colors = colors;
  sweepGradientInit();
  invalidate();
 }
 /**
  * 间隔角度大小
  *
  * @param lineWidth
  */
 public void setLineWidth(float lineWidth) {
  this.lineWidth = lineWidth;
  invalidate();
 }
 private int getDpValue(int w) {
  return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, w, getContext().getResources().getDisplayMetrics());
 }
 /**
  * 圆环宽度
  *
  * @param roundWidth 宽度
  */
 public void setRoundWidth(float roundWidth) {
  this.roundWidth = roundWidth;
  if (roundWidth > circleCenter) {
   this.roundWidth = circleCenter;
  }
  radius = (int) (circleCenter - this.roundWidth / 2); // 圆环的半径
  oval.left = circleCenter - radius;
  oval.right = circleCenter + radius;
  oval.bottom = circleCenter + radius;
  oval.top = circleCenter - radius;
  paint.setStrokeWidth(this.roundWidth);
  invalidate();
 }
 /**
  * 圆环的直径
  *
  * @param circleWidth 直径
  */
 public void setCircleWidth(int circleWidth) {
  this.circleWidth = circleWidth;
  circleCenter = circleWidth / 2;
  if (roundWidth > circleCenter) {
   roundWidth = circleCenter;
  }
  setRoundWidth(roundWidth);
  sweepGradient = new SweepGradient(this.circleWidth / 2, this.circleWidth / 2, colors, null);
  //旋转 不然是从0度开始渐变
  Matrix matrix = new Matrix();
  matrix.setRotate(-90, this.circleWidth / 2, this.circleWidth / 2);
  sweepGradient.setLocalMatrix(matrix);
 }
 /**
  * 渐变初始化
  */
 public void sweepGradientInit() {
  //渐变颜色
  sweepGradient = new SweepGradient(this.circleWidth / 2, this.circleWidth / 2, colors, null);
  //旋转 不然是从0度开始渐变
  Matrix matrix = new Matrix();
  matrix.setRotate(-90, this.circleWidth / 2, this.circleWidth / 2);
  sweepGradient.setLocalMatrix(matrix);
 }
 public void initView() {
  circleCenter = circleWidth / 2;//半径
  singlPoint = (float) 360 / (float) maxColorNumber;
  radius = (int) (circleCenter - roundWidth / 2); // 圆环的半径
  sweepGradientInit();
  mPaintText = new Paint();
  mPaintText.setColor(textColor);
  mPaintText.setTextAlign(Paint.Align.CENTER);
  mPaintText.setTextSize(textSize);
  mPaintText.setAntiAlias(true);
  paint = new Paint();
  paint.setColor(roundBackgroundColor);
  paint.setStyle(Paint.Style.STROKE);
  paint.setStrokeWidth(roundWidth);
  paint.setAntiAlias(true);
  // 用于定义的圆弧的形状和大小的界限
  oval = new RectF(circleCenter - radius, circleCenter - radius, circleCenter + radius, circleCenter + radius);
 }
 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  //背景渐变颜色
  paint.setShader(sweepGradient);
  canvas.drawArc(oval, -90, (float) (progress * 3.6), false, paint);
  paint.setShader(null);
  //是否是线条模式
  if (!isLine) {
   float start = -90f;
   float p = ((float) maxColorNumber / (float) 100);
   p = (int) (progress * p);
   for (int i = 0; i < p; i++) {
    paint.setColor(roundBackgroundColor);
    canvas.drawArc(oval, start + singlPoint - lineWidth, lineWidth, false, paint); // 绘制间隔快
    start = (start + singlPoint);
   }
  }
  //绘制剩下的空白区域
  paint.setColor(roundBackgroundColor);
  canvas.drawArc(oval, -90, (float) (-(100 - progress) * 3.6), false, paint);
  //绘制文字刻度
  for (int i = 1; i <= 10; i++) {
   canvas.save();// 保存当前画布
   canvas.rotate(360 / 10 * i, circleCenter, circleCenter);
   canvas.drawText(i * 10 + "", circleCenter, circleCenter - radius + roundWidth / 2 + getDpValue(4) + textSize, mPaintText);
   canvas.restore();//
  }
 }
 OnProgressScore onProgressScore;
 public interface OnProgressScore {
  void setProgressScore(float score);
 }
 public synchronized void setProgress(final float p) {
  progress = p;
  postInvalidate();
 }
 /**
  * @param p
  */
 public synchronized void setProgress(final float p, OnProgressScore onProgressScore) {
  this.onProgressScore = onProgressScore;
  progress = p;
  postInvalidate();
 }
}

以上所述是小编给大家介绍的Android 自定义圆形带刻度渐变色的进度条,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

时间: 2016-11-26

android自定义进度条渐变圆形

在安全卫生上,经常看到有圆形的进度条在转动,效果非常好看,于是就尝试去实现一下,具体实现过程不多说了,直接上效果图,先炫耀下. 效果图: 分析:比较常见于扫描结果.进度条等场景 利用canvas.drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)绘制圆弧 Paint的一些属性定义粗细.颜色.样式等 LinearGradient实现颜色的线型渐变 同样的道理,可以画出长条进度

Android实现歌词渐变色和进度的效果

要用TextView使用渐变色,那我们就必须要了解LinearGradient(线性渐变)的用法. LinearGradient的参数解释 LinearGradient也称作线性渲染,LinearGradient的作用是实现某一区域内颜色的线性渐变效果,看源码你就知道他是shader的子类. 它有两个构造函数 public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.T

Android设置PreferenceCategory背景颜色的方法

本文实例讲述了Android设置PreferenceCategory背景颜色的方法.分享给大家供大家参考.具体分析如下: 大家可能遇到,PreferenceCategory默认是黑色背景,如何我们更换了PreferenceScreen的背景,那么这种分隔栏看上去很丑,那么怎么更改背景呢?我们可以通过自定义VIEW来实现. 代码如下: public class MyPreferenceCategory extends PreferenceCategory { public MyPreference

Android 顶部标题栏随滑动时的渐变隐藏和渐变显示效果

各位早上好,话不多说,先上效果图: 注意顶部:首页TextView的变化(显示和隐藏)! 首先分析下:UI状态,其是由RecyclerView添加头部组成+RecyclerView 头部添加和RecyclerView分别引用如下:具体的分装数据的过程这里就不在说明,下篇博客会更加深入的写关于 RecyclerView总添加多种不同type类型 compile 'com.bartoszlipinski.recyclerviewheader:library:1.2.1' compile 'com.a

Android实现底部弹出PopupWindow背景逐渐变暗效果

在Android开发中,经常需要通过点击某个按钮弹出对话框或者选择框,通过Dialog或者PopupMenu.PopupWindow都能实现. 这里主要介绍后两者:PopupMenu.PopupWindow的实现. 先看两个效果图上边PopupMenu,下边PopupWindow: PopupMenu PopupWindow 一.PopupMenu实现: PopupMenu实现起来比较简单,主要用来实现根据按钮附近弹出的对话框. 首先定义一个menu文件\res\menu\headmenu.xm

Android仿淘宝商品拖动查看详情及标题栏渐变功能

绪论 最近一直比较忙,也没抽出时间来写博客,也不得不说是自己犯了懒癌,人要是一懒就什么事都不想做了,如果不能坚持下来的话,那么估计就废了,��.最近自己攒了好多东西,接下来的时间我会慢慢都分享出来的.好了废话不多说了,下面我们开始正题: 今天要分享的是淘宝的详情页,之前在淘宝上买东西的时候看到淘宝的详情页效果比较不错,所以今天就来仿一下它的效果吧,可能没有淘宝的好,希望见谅啊. 先上效果图: 这是淘宝的: 我自己做的: 怎么样效果还差不多吧?GIF图效果看的不太清楚,见谅. 下面我们来看看怎么实

Android实现渐变色的圆弧虚线效果

首先来看看效果图: 1,SweepGradient(梯度渲染) public SweepGradient (float cx, float cy, int[] colors, float[] positions) 扫描渲染,就是以某个点位中心旋转一周所形成的效果!参数依次是: cx:扫描的中心x坐标 cy:扫描的中心y坐标 colors:梯度渐变的颜色数组 positions:指定颜色数组的相对位置 public static final int[] SWEEP_GRADIENT_COLORS

Android实现沉浸式通知栏通知栏背景颜色跟随app导航栏背景颜色而改变

最近好多app都已经满足了沉浸式通知栏, 所谓沉浸式通知栏:就是把用来导航的各种界面操作空间隐藏在以程序内容为主的情景中,通过相对"隐形"的界面来达到把用户可视范围最大化地用到内容本身上. 而最新安卓4.4系统的通知栏沉浸模式就是在软件打开的时候通知栏和软件顶部颜色融为一体,这样不仅可以使软件和系统本身更加融为一体. 就是手机的通知栏的颜色不再是白色.黑色简单的两种了,本人用的小米4手机,米4手机中的自带软件都支持沉浸式通知栏, 举个例子:大家可以看一下自己的qq,它的标题的背景颜色是

Android编程实现自定义渐变颜色效果详解

本文实例讲述了Android编程实现自定义渐变颜色效果.分享给大家供大家参考,具体如下: 你是否已经厌恶了纯色的背景呢?那好,Android提供给程序员自定义渐变颜色的接口,让我们的界面炫起来吧. xml定义渐变颜色 首先,你在drawable目录下写一个xml,代码如下 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.

Android 微信6.1 tab栏图标和字体颜色渐变的实现

相信大家都见到了微信图标颜色渐变的过程,是不是感觉很牛逼?不得不说微信团队确实是很厉害的团队,不管是从设计还是开发人员. 今天我带大家来看看,微信 tab 栏图标和字体颜色渐变的过程.先上图吧!今天学了一招制作 gif 动态图的快捷方法.刚好用的上,以前一直想写点什么东西, 苦于一直不知道怎么生成动态图,现在终于学会了,哈哈,让我偷偷的乐一会.额,还是上图吧... 好了,效果图也看到了,那么我也就不多啰嗦了,直接进入主题,看代码 [java] view plain copy package mo

Android动画之渐变动画(Tween Animation)详解 (渐变、缩放、位移、旋转)

本文实例讲述了Android动画之渐变动画(Tween Animation).分享给大家供大家参考,具体如下: Android 平台提供了两类动画. 一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转.平移.放缩和渐变). 第二类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似. 下面就讲一下Tweene Animations. 主要类: Animation                  动画 AlphaAnimation          

android中实现背景图片颜色渐变方法

常用,记录一下. 效果图: 首先新建xml文件  bg_gradient.xml 复制代码 代码如下: <?xml version="1.0" encoding="utf-8"?>  <shape xmlns:android="http://schemas.android.com/apk/res/android" >        <gradient          android:startColor="

Android设置桌面背景图片的实现方法

1.设置桌面背景图片的方法 复制代码 代码如下: Resources res=getResources(); BitmapDrawable bmpDraw=(BitmapDrawable)res.getDrawable(R.drawable.icon); Bitmap bmp=bmpDraw.getBitmap(); try{ setWallpaper(bmp); }catch(IOException e) { e.printStackTrace(); } 2.在manifest中增加设置桌面的

Android中3种图片压缩处理方法

Android中图片的存在形式: 1:文件形式:二进制形式存在与硬盘中. 2:流的形式:二进制形式存在与内存中. 3:Bitmap的形式 三种形式的区别: 文件形式和流的形式:对图片体积大小并没有影响.也就是说,如果你手机SD卡上的图片通过流的形式读到内存中,在内存中的大小也是原图的大小. 注意:不是Bitmap的形式. Bitmap的形式:图片占用的内存会瞬间变大. 以下是代码的形式: /** * 图片压缩的方法总结 */ /* * 图片压缩的方法01:质量压缩方法 */ private Bi

Android中几种图片特效的处理的实现方法

 Android中几种图片特效的处理 这里有放大缩小图片,获得圆角图片,获得带倒影图片的几种方法及实现代码, package com.android.tutor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; i

Android中实现圆角图片的几种方法

Android中实现圆角图片有多种姿势,不知你解锁了几种? 方法一:setXfermode法 此种方式就是再new一个相同尺寸的bitmap,然后使用paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));先画圆角矩形,再画原始bitmap,然后就得到了一个圆角的bitmap了. public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) { Bitmap

Android编程之图片颜色处理方法

本文实例讲述了Android编程之图片颜色处理方法.分享给大家供大家参考,具体如下: 你想做到跟美图秀秀一样可以处理自己的照片,美化自己的照片吗?其实你也可以自己做一个这样的软件,废话不多说了,直接上图,上代码了! 效果图如下: 没处理前: 处理之后: MainActivity.java的代码如下: package net.loonggg.test; import android.app.Activity; import android.graphics.Bitmap; import andro

Android中简单调用图片、视频、音频、录音和拍照的方法

本文实例讲述了Android中简单调用图片.视频.音频.录音和拍照的方法.分享给大家供大家参考,具体如下: //选择图片 requestCode 返回的标识 Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT); //"android.intent.action.GET_CONTENT" innerIntent.setType(contentType); //查看类型 String IMAGE_UNSPECIFIED =

Vue项目中设置背景图片方法

在Vue项目开发中我们经常要向页面中添加背景图片,可是当我们在样式中添加了背景图片后,编译打包后,配置到服务器上时,由于路径解析的问题,图片并不能够正确的显示出来,如下CSS样式: background:url("../../assets/head.jpg"); 这个时候我们就要考虑使用其他的方式了,node中提供了一种比较有效的方式来解决这个问题: 1.在data中定义如下: export default { name: 'productdetailspage', data() {

Android中创建类似Instagram的渐变背景效果

我在我最近的项目用到这个效果,给大家分享下 https://github.com/zhaoweihaoChina/hnuplus 1. 在drawable文件夹创建一些渐变颜色的资源 color1.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <

HTML中使背景图片自适应浏览器大小实例详解

HTML中使背景图片自适应浏览器大小实例详解 解决办法: 1.图片不够大,又background属性不能拉伸图片: 2.只能用个div,把其z-index值设为负,并使这个div大小为整个body大小,在div里用<img> : 3.body的background属性去掉,要不然会被遮住. <html> <body> <div id="Layer1" style="position:absolute; left:0px; top:0p