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圆形向外扩散颜色渐浅动画

下载链接:http://download.csdn.net/detail/a876434758/8905773 首先自定义一个view package com.brucezee...

自定义View之实用渐变色进度条

在网上看到一个进度条效果图,非常美观,如下: 进行效果分解:1,渐变色,看起来颜色变化并不复杂,使用LinearGradient应该可以实现。 2,圆头,无非是画两个圆,外圆使用渐变色的颜色,内圆...
  • lintax
  • lintax
  • 2016年09月11日 20:58
  • 3321

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

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

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

Android——实现光点模糊渐变的自旋转圆环特效

项目中需要实现的效果图如下: 可以这个表盘看到中间部分都是没有什么难点的,主要是周围圆环的三种效果: 1:渐变色 2:尖端的白点模糊效果 3:路径绘制 最终实现的效果图如下: 完美实现了三点要...

Android ProgressBar自定义图片进度,自定义渐变色进度条

1 java.lang.Object 2    ↳    android.view.View 3   ...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

android Paint 渐变色

android Paint 渐变色 saint 2014年5月28日 Android, 移动 没有评论 一、LinearGradient线性渐变 在android平台中提...

Android环形颜色渐变进度条

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

Android自定义View和属性动画完美结合,创造出酷炫圆环动画,带标尺和进度

Android自定义View和属性动画完美结合,创造出酷炫圆环动画,带标尺和进度 无意中,在看了[【Android自定义View实战】之仿QQ运动步数圆弧及动画,Dylan计步中的控件StepAr...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android绘图---绘制颜色渐变的圆圈进度条
举报原因:
原因补充:

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