Android 自定义进度条ColorfulProgressBar,原理简单、效果很棒

Android-ColorfulProgressBar

关于我,欢迎关注
博客:ccapton(http://blog.csdn.net/ccapton) 微信:Ccapton
简介:
这是一个自定义的Progressbar,效果看着还行吧,滚动的双色斜条作为进度条,有点类似Bootstrap风格。原生Progress的基本操作都有,自行观摩我的源码吧,挺简单的。
示例:

演示Demo
demo下载:
https://github.com/Ccapton/Android-ColorfulProgressBar/blob/master/ColorfulProgressBarDemo_1_0_3.apk
特性
与原生Progress相比,感觉更漂亮一点,可以显示进度值,背景凹凸感明显,进度条效果更加立体。
原理说明
额,挺简单的。不过感觉我的做法有点复杂了,我先自定义了一个View,专门作为进度条的显示图层,如下所示

然后将其布局在高度不超过20dp的ColorfulProgressBar父布局中,设置Y方向的偏移量,然后动画循环改变Y坐标,实现斜条滚动的动画效果,当你调用setProgress方法时,则改变其在父布局的X坐标实现进度显示的功能,进度文字同样原理添加到了父布局中。
具体代码
ColorfulView.java 这个类实例化后添加到视图当中后,就如上如所示。
package com.capton.colorfulprogressbar; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.support.annotation.Nullable; import android.view.View; /** *这是一个绘制了多个等腰直角三角形的View,呈现出一个由很多个斜条纹组成的双色画布 * 可以自行通过new ColorfulView(Context context,int width,Paint paint,Paint paint2)方法,构建出来看效果 * Created by capton on 2017/8/10. */ public class ColorfulView extends View {private Paint paint; private Paint paint2; private int mWidth; public ColorfulView(Context context,int width,Paint paint,Paint paint2) { super(context); mWidth=width; this.paint=paint; this.paint2=paint2; ; }@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(mWidth,mWidth); }@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float x,y; float x2,y2; for (int i = 30; i > 0; i--) { Path p1=new Path(); x=y=((float)mWidth/30)*i; p1.lineTo(0,y); p1.lineTo(x,0); p1.lineTo(0,0); p1.close(); if(i%2==0) { canvas.drawPath(p1, paint); }else { canvas.drawPath(p1, paint2); } } for (int i = 0; i < 30; i++) { Path p2=new Path(); x2=y2=((float)mWidth/30)*i; p2.moveTo(mWidth,mWidth); p2.lineTo(mWidth,y2); p2.lineTo(x2,mWidth); p2.lineTo(mWidth,mWidth); p2.close(); if(i%2!=0) { canvas.drawPath(p2, paint); }else { canvas.drawPath(p2, paint2); } } } }

主体ColorfulProgressbar.java
package com.capton.colorfulprogressbar; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.ViewGroup; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.widget.TextView; /** * Created by capton on 2017/8/10. */ public class ColorfulProgressbar extends ViewGroup {public static final String STYLE_NORMAL="normal"; //正常单色样式 public static final String STYLE_COLORFUL="colorful"; //双色样式 publicString style="colorful"; private ColorfulView colofulView; //双色View private TextView progressView; // 第二进度条 private TextView backgroundMaskView; // 背景罩 private TextView maskView; // 进度条白色渐变图层 private TextView percentView; //文字显示进度层 private Paint progressPaint=new Paint(); //颜色一画笔 private Paint progressPaint2=new Paint(); //颜色二画笔 private Paint backgroundPaint=new Paint(); //背景画笔privateint maxHeight; // 高度最大值 privateint mHeight; // 高度 privateint mWidth; // 宽度privatelong progress; //进度值 privatelong secondProgress; //第二进度值 privatelong maxProgress=100; //默然最大进度100 privateint backgroundColor=getResources().getColor(R.color.progressBg); //背景颜色 privateint secondProgressColor=getResources().getColor(R.color.secondProgressColor); //第二进度条颜色 privateint progressColor=getResources().getColor(R.color.colorAccent); //进度条颜色一 privateint progressColor2=getResources().getColor(R.color.ltcolorAccent); //进度条颜色二 privateint percentColor=Color.YELLOW; //进度文字的颜色,默认黄色 privateint percentShaderColor=Color.DKGRAY; //进度文字的阴影颜色,默认暗灰色private TranslateAnimation translateAnimation; //双色进度条的动画1 private TranslateAnimation translateAnimation2; //双色进度条的动画2 private boolean animationOn=true; //动画开启的标志位 private boolean animationCancle; //动画取消的标志位private boolean showPercent=true; // 是否显示进度文字的标志位 private boolean setBackgroudColor; // 是否改变背景颜色的标志位private boolean isSetBackgroudColorByXml; public ColorfulProgressbar(Context context) { super(context); setWillNotDraw(false); //自定义ViewGroup,默认不调用onDraw方法,而这里有很多步骤需要在ondraw中操作,所以调用setWillNotDraw(false) initSettings(); } public ColorfulProgressbar(Context context, AttributeSet attrs) { this(context, attrs,0); } public ColorfulProgressbar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setWillNotDraw(false); //自定义ViewGroup,默认不调用onDraw方法,而这里有很多步骤需要在ondraw中操作,所以调用setWillNotDraw(false) getParameter(context,attrs); isSetBackgroudColorByXml=true; }/** * 从xml中获取各个属性 * @param context * @param attrs */ private void getParameter(Context context, AttributeSet attrs){ if(attrs!=null) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ColorfulProgressbar); style = ta.getString(R.styleable.ColorfulProgressbar_style); if (!STYLE_NORMAL.equals(style) && !STYLE_COLORFUL.equals(style)) { style = STYLE_COLORFUL; //如果没有在xml中显示设置style,默认使用双色进度条 } progress = ta.getInteger(R.styleable.ColorfulProgressbar_progress, (int)progress); secondProgress = ta.getInteger(R.styleable.ColorfulProgressbar_secondProgress,(int)secondProgress); maxProgress = ta.getInteger(R.styleable.ColorfulProgressbar_max, (int) maxProgress); backgroundColor = ta.getColor(R.styleable.ColorfulProgressbar_backgroundColor, backgroundColor); progressColor = ta.getColor(R.styleable.ColorfulProgressbar_progressColor1, progressColor); progressColor2 = ta.getColor(R.styleable.ColorfulProgressbar_progressColor2, progressColor2); animationOn = ta.getBoolean(R.styleable.ColorfulProgressbar_animation,animationOn); ta.recycle(); initSettings(); } }private void initSettings() { partition2= (float)this.progress/maxProgress; //进度条百分比 partition= (float)this.secondProgress/maxProgress; //第二进度条百分比 backgroundPaint.setAntiAlias(true); backgroundPaint.setColor(backgroundColor); }@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize=MeasureSpec.getSize(widthMeasureSpec); int widthMode=MeasureSpec.getMode(widthMeasureSpec); int heightSize=MeasureSpec.getSize(heightMeasureSpec); int heightMode=MeasureSpec.getMode(heightMeasureSpec); widthSize=widthMode==MeasureSpec.EXACTLY?widthSize:DisplayUtil.dip2px(getContext(),200); heightSize=heightMode==MeasureSpec.EXACTLY?heightSize:DisplayUtil.dip2px(getContext(),4); /* * 当你设置高度大于20dp时,强制高度变为20dp,太高了不美观。 * */ maxHeight=DisplayUtil.dip2px(getContext(),20); if(mHeight>maxHeight) { mHeight = maxHeight; } /* * 设置高度 * */ if(mHeight>0){ heightSize=mHeight; } else { heightSize=heightSize>maxHeight?maxHeight:heightSize; }/* * 在高度小于10dp时,强制不能使用文字显示进度,因为高度实在是太小了,在这个高度下字体看不清楚,放在进度条外又不美观,只好折中设计了。 * */ if(heightSize0){ widthSize=mWidth; } setMeasuredDimension(widthSize,heightSize); //确定主视图宽高}boolean once; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {if(!once) { progressPaint.setColor(progressColor); progressPaint2.setColor(progressColor2); progressPaint.setAntiAlias(true); progressPaint2.setAntiAlias(true); progressView = new TextView(getContext()); progressView.setWidth(getMeasuredWidth()); progressView.setHeight(getMeasuredHeight()); progressView.setBackgroundColor(secondProgressColor); backgroundMaskView= new TextView(getContext()); backgroundMaskView.setWidth(getMeasuredWidth()); backgroundMaskView.setHeight(getMeasuredHeight()); backgroundMaskView.setBackgroundResource(R.drawable.background); switch (style) { case STYLE_COLORFUL: colofulView = new ColorfulView(getContext(), getMeasuredWidth(), progressPaint, progressPaint2); break; case STYLE_NORMAL: colofulView = new ColorfulView(getContext(), getMeasuredWidth(), progressPaint, progressPaint); break; }percentView = new TextView(getContext()); percentView.setText((int)((float)partition2*100)+"%"); percentView.setTextSize(DisplayUtil.px2sp(getContext(), (float) (getMeasuredHeight()*0.8))); percentView.setGravity(Gravity.CENTER); percentView.setShadowLayer(2,1,2,percentShaderColor); percentView.setTextColor(percentColor); percentView.measure(0,0); int textWidth = percentView.getMeasuredHeight()*2; int textHeight = percentView.getMeasuredHeight(); maskView = new TextView(getContext()); maskView.setWidth(getMeasuredWidth()); maskView.setHeight(getMeasuredHeight() * 2 / 3); maskView.setBackgroundResource(R.drawable.progress_mask); /* * 依次添加第二进度条,背景罩,双色进度条(第一进度条),白色渐变层,百分比文字显示层等四个子View * */ addView(progressView); addView(backgroundMaskView); addView(colofulView); addView(maskView); addView(percentView); getChildAt(0).layout(0, 0, getMeasuredWidth(), getMeasuredHeight()); //布局第二进度条位置 getChildAt(1).layout(0, 0, getMeasuredWidth(), getMeasuredHeight()); //布局背景罩int ChildHeight = getMeasuredWidth(); getChildAt(2).layout(0, -ChildHeight + getMeasuredHeight(), getMeasuredWidth(), getMeasuredWidth()); //布局双色进度条 /* * 根据标识位,为双色进度条设置位移动画(无限上下移动,视觉上达到斜条移动的效果) * */ if (animationOn) { translateAnimation = new TranslateAnimation(0, 0, 0, ChildHeight - getMeasuredHeight()); translateAnimation.setDuration((long) (8000 * (float) getMeasuredWidth() / DisplayUtil.getScreenWidthPx(getContext()))); translateAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); translateAnimation.setRepeatCount(-1); translateAnimation.setRepeatMode(Animation.REVERSE); getChildAt(2).setAnimation(translateAnimation); translateAnimation.start(); }getChildAt(3).layout(0, 0, getMeasuredWidth(), getMeasuredHeight() * 2 / 3); //布局白色渐变层getChildAt(4).layout(0, 0, textWidth,textHeight); //布局百分比文字显示层 /* * 根据标志位,确定是否显示百分比文字显示层。 * */ if(showPercent){ getChildAt(4).setVisibility(VISIBLE); }else { getChildAt(4).setVisibility(GONE); }/* *设置默认背景图,你当然也可以使用纯色的资源。这里我用了一个黑色透明渐变的背景,呈现一个由阴影效果的凹槽 * */ setBackgroundResource(R.drawable.background); once=true; } }public void showPercentText(boolean showPercent){ this.showPercent=showPercent; postInvalidate(); }public int getSecondProgressColor() { return secondProgressColor; }public void setSecondProgressColor(int secondProgressColor) { this.secondProgressColor = secondProgressColor; postInvalidate(); } public void setSecondProgressColorRes(int secondProgressColorRes) { this.secondProgressColor =getResources().getColor(secondProgressColorRes); postInvalidate(); }public int getPercentColor() { return percentColor; }public void setPercentColor(int percentColor) { this.percentColor = percentColor; }public void setPercentColorRes(int percentColorRes) { this.percentColor = getResources().getColor(percentColorRes); }public int getPercentShadeColor() { return percentShaderColor; }public void setPercentShaderColor(int percentShadeColor) { this.percentShaderColor = percentShadeColor; } public void setPercentShaderColorRes(int percentShaderColorRes) { this.percentShaderColor = getResources().getColor(percentShaderColorRes); }public String getStyle() { return style; }public void setStyle(String style) { this.style = style; }public int getProgressColor() { return progressColor; }public void setProgressColor(int progressColor) { this.progressColor = progressColor; } public void setProgressColorRes(int progressColorRes) { this.progressColor = getResources().getColor(progressColorRes); }public int getProgressColor2() { return progressColor2; }public void setProgressColor2(int progressColor2) { this.progressColor2 = progressColor2; } public void setProgressColor2Res(int progressColor2Res) { this.progressColor2 = getResources().getColor(progressColor2Res); }public void setAnimation(boolean animationOn){ this.animationOn=animationOn; }public long getSecondProgress() { return secondProgress; } private float partition; public void setSecondProgress(long secondProgress) { this.secondProgress = secondProgress; partition= (float)this.secondProgress/maxProgress; postInvalidate(); }public int getBackgroundColor() { return backgroundColor; }public void setBackgroundColor(int backgroundColor) { this.backgroundColor = backgroundColor; setBackgroudColor=true; postInvalidate(); }public void setBackgroundColorRes(int backgroundColorRes) { this.backgroundColor = getResources().getColor(backgroundColorRes); setBackgroudColor=true; postInvalidate(); }public void setHeight(int height){ mHeight=height; } public void setWidth(int width){ mWidth=width; }public void setMaxProgress(long progress){ maxProgress=progress; }public long getMaxProgress(){ return maxProgress; }private float partition2; public void setProgress(long progress){ this.progress=progress; partition2= (float)this.progress/maxProgress; postInvalidate(); }public long getProgress(){ return this.progress; }@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (getChildAt(0) != null) { int moveX = getMeasuredWidth() - (int) (partition * getMeasuredWidth()); getChildAt(0).setX(-moveX); } if (getChildAt(2) != null) { int moveX = getMeasuredWidth() - (int) (partition2 * getMeasuredWidth()); getChildAt(2).setX(-moveX); }if (getChildAt(3) != null) { int moveX = getMeasuredWidth() - (int) (partition2 * getMeasuredWidth()); getChildAt(3).setX(-moveX); } if (getChildAt(4) != null) {if(getChildAt(2).getX()+getMeasuredWidth()>getChildAt(4).getMeasuredHeight()*2) { getChildAt(4).setX(getChildAt(2).getX()+getMeasuredWidth()-getChildAt(4).getMeasuredHeight()*2); } percentView.setText((int) ((float) partition2 * 100) + "%"); /* * 根据标志位,确定是否显示百分比文字显示层。 * */ if(showPercent){ getChildAt(4).setVisibility(VISIBLE); }else { getChildAt(4).setVisibility(GONE); } }if (!animationOn) { if (translateAnimation != null) { translateAnimation.cancel(); animationCancle = true; } } else { if (animationCancle) { Log.w("onDraw", "translateAnimationanimationCancle"); translateAnimation.reset(); getChildAt(2).setAnimation(translateAnimation); translateAnimation.startNow(); animationCancle = false; } }if(setBackgroudColor) { backgroundPaint.setColor(backgroundColor); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); } else{ setBackgroundResource(R.drawable.background); if(isSetBackgroudColorByXml) canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); } } }

【Android 自定义进度条ColorfulProgressBar,原理简单、效果很棒】还有一个工具类DisplayUtil就不贴了,主要是负责dp,px与sp的转换任务。
项目地址
https://github.com/Ccapton/Android-ColorfulProgressBar
我的Github
https://github.com/Ccapton
作者的话
挺漂亮的ProgressBar,就是没啥技术含量。。。。具体需求大家自己随便研究琢磨

    推荐阅读