这个自定义的view,完全脱离了android自带的ProgressView,并且没使用一张图片,这样就能更好的降低程序代码上的耦合性!
下面我贴出代码 ,大概讲解一下实现思路吧!
package com.spring.progressview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; /*** * 自定义进度条 * @author spring sky * Email:vipa1888@163.com * 创建时间:2014-1-6下午3:28:51 */ public class SpringProgressView extends View { /**分段颜色*/ private static final int[] SECTION_COLORS = {Color.GREEN,Color.YELLOW,Color.RED}; /**进度条最大值*/ private float maxCount; /**进度条当前值*/ private float currentCount; /**画笔*/ private Paint mPaint; private int mWidth,mHeight; public SpringProgressView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } public SpringProgressView(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public SpringProgressView(Context context) { super(context); initView(context); } private void initView(Context context) { } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint = new Paint(); mPaint.setAntiAlias(true); int round = mHeight/2; System.out.println("max="+maxCount + " current="+currentCount); mPaint.setColor(Color.rgb(71, 76, 80)); RectF rectBg = new RectF(0, 0, mWidth, mHeight); canvas.drawRoundRect(rectBg, round, round, mPaint); mPaint.setColor(Color.BLACK); RectF rectBlackBg = new RectF(2, 2, mWidth-2, mHeight-2); canvas.drawRoundRect(rectBlackBg, round, round, mPaint); float section = currentCount/maxCount; RectF rectProgressBg = new RectF(3, 3, (mWidth-3)*section, mHeight-3); if(section <= 1.0f/3.0f){ if(section != 0.0f){ mPaint.setColor(SECTION_COLORS[0]); }else{ mPaint.setColor(Color.TRANSPARENT); } }else{ int count = (section <= 1.0f/3.0f*2 ) ? 2 : 3; int[] colors = new int[count]; System.arraycopy(SECTION_COLORS, 0, colors, 0, count); float[] positions = new float[count]; if(count == 2){ positions[0] = 0.0f; positions[1] = 1.0f-positions[0]; }else{ positions[0] = 0.0f; positions[1] = (maxCount/3)/currentCount; positions[2] = 1.0f-positions[0]*2; } positions[positions.length-1] = 1.0f; LinearGradient shader = new LinearGradient(3, 3, (mWidth-3)*section, mHeight-3, colors,null, Shader.TileMode.MIRROR); mPaint.setShader(shader); } canvas.drawRoundRect(rectProgressBg, round, round, mPaint); } private int dipToPx(int dip) { float scale = getContext().getResources().getDisplayMetrics().density; return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1)); } /*** * 设置最大的进度值 * @param maxCount */ public void setMaxCount(float maxCount) { this.maxCount = maxCount; } /*** * 设置当前的进度值 * @param currentCount */ public void setCurrentCount(float currentCount) { this.currentCount = currentCount > maxCount ? maxCount : currentCount; invalidate(); } public float getMaxCount() { return maxCount; } public float getCurrentCount() { return currentCount; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.EXACTLY || widthSpecMode == MeasureSpec.AT_MOST) { mWidth = widthSpecSize; } else { mWidth = 0; } if (heightSpecMode == MeasureSpec.AT_MOST || heightSpecMode == MeasureSpec.UNSPECIFIED) { mHeight = dipToPx(15); } else { mHeight = heightSpecSize; } setMeasuredDimension(mWidth, mHeight); } }
以上代码就是该控件的全部核心代码了
具体思路:
1.进度条,其实就是一个最大值和最小值的比例值,这个比例就是 当前值/最大值;
2.自定义的圆角问题,只要还是用到了Canvar的画板的drawRoundRect ;
3.渐变色:LinearGradient对象渲染,具体渲染的比例要自己计算,目前我的程序提供3中颜色渲染,具体规则是:
(1)当进度条占最大值的三分之一以下,则提供一种颜色
(2)当最大值超过三分之一话,就区分是否超过三分之二,如果超过则用三种,否则用两种颜色,因为三种颜色各占总进度条的三分之一,这是一个初中数据的问题,自己慢慢画图吧!
4.怎么把进度条放在一个有圆角背景的上面,这个就是绘制两个圆角长方形:第一个作为背景,第二个作为进度条的实体,具体第二个进度的实体占多长,就是当前 currentCount/maxCount*自定义View的长度 ;
其他的,没啥技术难点了,做这种自定义控件,最重要的是,自定要根据人家的效果图,看懂实现思路,具体代码简历在思路上的,否则只会纸上谈兵!如果看不懂,就要多画图,具体的一步步计算,天长地久,也就能“练”出来了!
下面提供一个demo下载地址:SpringProgressDemo