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,就是没啥技术含量。。。。具体需求大家自己随便研究琢磨