android绘图---绘制颜色渐变的圆圈进度条

原创 2015年07月08日 16:30:47

package com.example.fox_draw_view;

/**
* @auth:foxcen
* @功能:画圆形进度条
*/
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.Log;
import android.view.View;

/**
* 仿iphone带进度的进度条,线程安全的View,可直接在线程中更新进度
* @author xiaanming
*
*/
public class RoundProgressBar extends View {
/**
* 画笔对象的引用
*/
private Paint paint;

/**
 * 圆环的颜色
 */
private int roundColor;

/**
 * 圆环进度的颜色
 */
private int roundProgressColor;

/**
 * 中间进度百分比的字符串的颜色
 */
private int textColor;

/**
 * 中间进度百分比的字符串的字体
 */
private float textSize;

/**
 * 圆环的宽度
 */
private float roundWidth;

/**
 * 最大进度
 */
private int max;

/**
 * 当前进度
 */
private int progress;
/**
 * 是否显示中间的进度
 */
private boolean textIsDisplayable;

/**
 * 进度的风格,实心或者空心
 */
private int style;

public static final int STROKE = 0;
public static final int FILL = 1;

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);

    paint = new Paint();



    TypedArray mTypedArray = context.obtainStyledAttributes(attrs,
            R.styleable.RoundProgressBar);

    //获取自定义属性和默认值
    roundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.WHITE);
    roundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.YELLOW);
    textColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textColor, Color.WHITE);
    textSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 64);
    roundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 8);
    max = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100);
    textIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true);
    style = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0);

    mTypedArray.recycle();
}



@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    /**
     * 画最外层的大圆环
     */
    int centre = getWidth()/2; //获取圆心的x坐标
    int radius = (int) (centre - roundWidth/2); //圆环的半径
    paint.setColor(roundColor); //设置圆环的颜色
    paint.setStyle(Paint.Style.STROKE); //设置空心
    paint.setStrokeWidth(roundWidth); //设置圆环的宽度
    paint.setAntiAlias(true);  //消除锯齿 
    canvas.drawCircle(centre, centre, radius, paint); //画出圆环

    Log.e("log", centre + "");

    /**
     * 画进度百分比
     */
    paint.setStrokeWidth(0); 
    paint.setColor(textColor);
    paint.setTextSize(textSize);
    paint.setTypeface(Typeface.DEFAULT_BOLD); //设置字体
    int percent = (int)(((float)progress / (float)max) * 100);  //中间的进度百分比,先转换成float在进行除法运算,不然都为0
    float textWidth = paint.measureText("");   //测量字体宽度,我们需要根据字体的宽度设置在圆环中间

    if(textIsDisplayable && percent != 0 && style == STROKE){
        canvas.drawText("", centre - textWidth / 2, centre + textSize/2, paint); //画出进度百分比
    }


    /**
     * 画圆弧 ,画圆环的进度
     */

    //设置进度是实心还是空心
    paint.setStrokeWidth(roundWidth); //设置圆环的宽度
    paint.setColor(roundProgressColor);  //设置进度的颜色
    RectF oval = new RectF(centre - radius, centre - radius, centre
            + radius, centre + radius);  //用于定义的圆弧的形状和大小的界限
            Shader mShader=new  SweepGradient(centre, centre, context.getResources().getColor(R.color.start_color), context.getResources().getColor(R.color.end_color));

    switch (style) {
    case STROKE:{
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(oval, -90, 360 * progress / max, false, paint);  //根据进度画圆弧
        break;
    }
    case FILL:{
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        if(progress !=0)
            canvas.drawArc(oval, -90, 360 * progress / max, true, paint);  //根据进度画圆弧
        break;
    }
    }
    setProgress(40);
}


public synchronized int getMax() {
    return max;
}


/**
 * 设置进度的最大值
 * @param max
 */
public synchronized void setMax(int max) {
    if(max < 0){
        throw new IllegalArgumentException("max not less than 0");
    }
    this.max = max;
}


/**
 * 获取进度.需要同步
 * @return
 */
public synchronized int getProgress() {
    return progress;
}


/**
 * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
 * 刷新界面调用postInvalidate()能在非UI线程刷新
 * @param progress
 */
public synchronized void setProgress(int progress) {
    if(progress < 0){
        throw new IllegalArgumentException("progress not less than 0");
    }
    if(progress > max){
        progress = max;
    }
    if(progress <= max){
        this.progress = progress;
        postInvalidate();
    }

}


public int getCricleColor() {
    return roundColor;
}


public void setCricleColor(int cricleColor) {
    this.roundColor = cricleColor;
}


public int getCricleProgressColor() {
    return roundProgressColor;
}


public void setCricleProgressColor(int cricleProgressColor) {
    this.roundProgressColor = cricleProgressColor;
}


public int getTextColor() {
    return textColor;
}


public void setTextColor(int textColor) {
    this.textColor = textColor;
}


public float getTextSize() {
    return textSize;
}


public void setTextSize(float textSize) {
    this.textSize = textSize;
}


public float getRoundWidth() {
    return roundWidth;
}


public void setRoundWidth(float roundWidth) {
    this.roundWidth = roundWidth;
}

}

知识点1:
就像上面的显示效果一样一束白光闪过,这种效果主要还是使用了LinearGradient类来进行的

LinearGradient也称作线性渲染,LinearGradient的作用是实现某一区域内颜色的线性渐变效果

它有两个构造函数
代码如下 复制代码
public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)

其中,参数x0表示渐变的起始点x坐标;参数y0表示渐变的起始点y坐标;参数x1表示渐变的终点x坐标;参数y1表示渐变的终点y坐标 ;color0表示渐变开始颜色;color1表示渐变结束颜色;参数tile表示平铺方式。

Shader.TileMode有3种参数可供选择,分别为CLAMP、REPEAT和MIRROR:

CLAMP的作用是如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色

REPEAT的作用是在横向和纵向上以平铺的形式重复渲染位图

MIRROR的作用是在横向和纵向上以镜像的方式重复渲染位图

public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile);

其中,参数x0表示渐变的起始点x坐标;参数y0表示渐变的起始点y坐标;参数x1表示渐变的终点x坐标;参数y1表示渐变的终点y坐标;参数colors表示渐变的颜色数组;参数positions用来指定颜色数组的相对位置;参数tile表示平铺方式。通常,参数positions设为null,表示颜色数组以斜坡线的形式均匀分布。

下面这段代码是直接从git上面的项目拷贝下来的
代码如下 复制代码

package com.example.shimmer;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.widget.TextView;

public class MyTextView extends TextView {

private LinearGradient mLinearGradient;
private Matrix mGradientMatrix;
private Paint mPaint;
private int mViewWidth = 0;
private int mTranslate = 0;

private boolean mAnimating = true;

public MyTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    if (mViewWidth == 0) {
        mViewWidth = getMeasuredWidth();
        if (mViewWidth > 0) {
            mPaint = getPaint();
            mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0,
                    new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff },
                    new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP);
            mPaint.setShader(mLinearGradient);
            mGradientMatrix = new Matrix();
        }
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mAnimating && mGradientMatrix != null) {
        mTranslate += mViewWidth / 10;
        if (mTranslate > 2 * mViewWidth) {
            mTranslate = -mViewWidth;
        }
        mGradientMatrix.setTranslate(mTranslate, 0);
        mLinearGradient.setLocalMatrix(mGradientMatrix);
        postInvalidateDelayed(50);
    }
}

}

这段代码主要是分两步:一个是在onSizeChanged()即大小发生改变的时候,另外一个是onDraw()主要是用来做动画的效果的,

首先我们先来onSizeChanged()里面的代码,在这段代码中主要是定义了LinearGradient:
代码如下 复制代码

mLinearGradient = new LinearGradient(-mViewWidth, 0, 0, 0, new int[] { 0x33ffffff, 0xffffffff, 0x33ffffff },new float[] { 0, 0.5f, 1 }, Shader.TileMode.CLAMP);

这段代码可以这么理解,它定义了一组渐变的数值是{ 0x33ffffff, 0xffffffff, 0x33ffffff },这组数值分别在相对应的0,0.5,1中显示,0位置对应0x33ffffff颜色,0.5位置对应0xffffffff,1位置对应0x33ffffff,这个渐变的初始位置是在手机屏幕的外面x=(-mViewWidth,0)就是屏幕外面

最后来看一下这个onDraw()方法里面是如何做动画的
代码如下 复制代码

mTranslate += mViewWidth / 10;很简单表示每一次运动的递增值

    if (mTranslate > 2 * mViewWidth) {
        mTranslate = -mViewWidth;
    }

Android渐变色画笔 自定义View渐变色

Android开发中用到渐变色背景场景很多也很容易实现。在res/drawable目录下添加一个xml文件(命名不限)里面的内容大体如下 ...
  • lan_hz007
  • lan_hz007
  • 2017年03月17日 00:58
  • 3023

Android 给AChartEngine绘制的曲线图加渐变色(修改AChartEngine源码)

AChartEngine是一个安卓的图标框架,支持各种图标。以下说的针对曲线图。 百度一通没发现,然后在http://stackoverflow.com/questions/16140546/andr...
  • u010237531
  • u010237531
  • 2015年09月16日 17:31
  • 2543

【Android】动态渐变色的扇形

动态渐变色的扇形
  • u013580497
  • u013580497
  • 2015年09月17日 11:13
  • 1062

Android实现圆弧形渐变色进度条

效果图:我写的这篇博客个人感觉非常的不详细,这也是根据UI设计的,不过大家掌握下文所点出来的重点方法也可以将其绘制出来,这里就不详细介绍绘制流程了 UI分析:这个UI细分为表盘刻度、进度条底色、进度...
  • ForrestL
  • ForrestL
  • 2016年08月23日 10:09
  • 7143

Android 绘图基础:Canvas画布——自定义View基础(绘制表盘、矩形、圆形、弧、渐变)

今天学习了Canvas画布,感觉挺好玩的,通过它我们可以自定义一个View,设置View的相关效果之类的。感觉用法差不多,重要的是要理解方法中传入的参数的含义,比如float类型的参数,传递的是坐标,...
  • danfengw
  • danfengw
  • 2015年09月16日 22:33
  • 3856

android UI--canvas相关(渐变、阴影、path)

1、setShader Paint对象的setShader函数,我的感觉是设置一种方式来填充图形。 可以设置为渐变,代码如下: [java] view plain...
  • jackchen95
  • jackchen95
  • 2013年11月27日 14:07
  • 9350

Android画个颜色渐变的圆环玩玩

先看下最终的效果开始实现新建一个DoughnutView继承View public class DoughnutView extends View { }先重写onMeasure方法,为什...
  • qp23401
  • qp23401
  • 2015年12月21日 18:26
  • 6225

Android环形颜色渐变进度条

距离上次写博客又过了许久的了,懒起来还真是莫法,废话就不说多了,哈哈。今天要讲的就是一种常见的“环形颜色渐变的圆环进度条”,先看看效果就知道是怎样的了,后面也有免积分Demo下载地址。 录制得不是...
  • ywl5320
  • ywl5320
  • 2016年01月12日 22:57
  • 3350

自定义View之渐变色圆形进度条

先展示下效果图,然后按照自定义view的步骤来实现。 目标是渐变色圆形进度条,那么,使用canvas画弧形是基础了,另外是渐变色的效果,这里使用LinearGradient来实现。 既然是提供一个进...
  • lintax
  • lintax
  • 2016年09月06日 22:01
  • 2677

Android自定义圆形渐变进度条

作为一个自学入门android的人来说,刚接触自定义view时完全处于懵逼状态,不过还好,大神们已经铺好了路,尔等只需稍加钻研即可小有成就的,废话不多说了,先上效果图! 理清下此view...
  • u014602775
  • u014602775
  • 2016年12月08日 16:33
  • 218
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android绘图---绘制颜色渐变的圆圈进度条
举报原因:
原因补充:

(最多只允许输入30个字)