效果圖:
演示Demo
demo下載: https://github.com/Ccapton/Android-ColorfulProgressBar/blob/master/ColorfulProgressBarDemo_1_0_3.apk
特性
與原生Progress相比骗灶,感覺更漂亮一點(diǎn),可以顯示進(jìn)度值脱羡,背景凹凸感明顯,進(jìn)度條效果更加立體帆竹。
原理說明
額栽连,挺簡單的侨舆。不過感覺我的做法有點(diǎn)復(fù)雜了态罪,我先自定義了一個(gè)View,專門作為進(jìn)度條的顯示圖層,如下所示
將其布局在高度不超過20dp的ColorfulProgressBar父布局中,設(shè)置Y方向的偏移量耗啦,然后動(dòng)畫循環(huán)改變Y坐標(biāo)帜讲,實(shí)現(xiàn)斜條滾動(dòng)的動(dòng)畫效果,當(dāng)你調(diào)用setProgress方法時(shí)似将,則改變其在父布局的X坐標(biāo)實(shí)現(xiàn)進(jìn)度顯示的功能在验,進(jìn)度文字同樣原理添加到了父布局中腋舌。
項(xiàng)目地址
https://github.com/Ccapton/Android-ColorfulProgressBar
我的Github:
https://github.com/Ccapton
相關(guān)代碼
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"; //雙色樣式
public String style="colorful";
private ColorfulView colofulView; //雙色View
private TextView progressView; // 第二進(jìn)度條
private TextView maskView; // 季度條白色漸變圖層
private TextView percentView; //文字顯示進(jìn)度層
private Paint progressPaint=new Paint(); //顏色一畫筆
private Paint progressPaint2=new Paint(); //顏色二畫筆
private Paint backgroundPaint=new Paint(); //背景畫筆
private int maxHeight; //ColorfulProgressbar高度最大值
private int mHeight; //ColorfulProgressbar高度
private int mWidth; //ColorfulProgressbar寬度
private long progress; //進(jìn)度值
private long secondProgress; //第二進(jìn)度值
private long maxProgress=100; //默然最大進(jìn)度100
private int backgroundColor=getResources().getColor(R.color.progressBg); //背景顏色
private int secondProgressColor=getResources().getColor(R.color.secondProgressColor); //第二進(jìn)度條顏色
private int progressColor=getResources().getColor(R.color.colorAccent); //進(jìn)度條顏色一
private int progressColor2=getResources().getColor(R.color.ltcolorAccent); //進(jìn)度條顏色二
private int percentColor=Color.DKGRAY; //進(jìn)度文字的顏色赞辩,默認(rèn)暗灰色
private int percentShadeColor=Color.WHITE; //進(jìn)度文字的陰影顏色授艰,默認(rèn)白色
private TranslateAnimation translateAnimation; //雙色進(jìn)度條的動(dòng)畫
private boolean animationOn=true; //動(dòng)畫開啟的標(biāo)志位
private boolean animationCancle; //動(dòng)畫取消的標(biāo)志位
private boolean showPercent=true; // 是否顯示進(jìn)度文字的標(biāo)志位
private boolean setBackgroudColor; // 是否改變背景顏色的標(biāo)志位
public ColorfulProgressbar(Context context) {
this(context,null);
}
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淮腾,默認(rèn)不調(diào)用onDraw方法,而這里有很多步驟需要在ondraw中操作忘古,所以調(diào)用setWillNotDraw(false)
mHeight=DisplayUtil.dip2px(context,4); //默認(rèn)進(jìn)度條高度為4dp
getParameter(context,attrs);
}
/**
* 從xml中獲取各個(gè)屬性
* @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中顯示設(shè)置style诅诱,默認(rèn)使用雙色進(jìn)度條
}
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);
ta.recycle();
partition2= (float)this.progress/maxProgress; //進(jìn)度條百分比
partition= (float)this.secondProgress/maxProgress; //第二進(jìn)度條百分比
}
}
@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);
/*
* 當(dāng)你設(shè)置高度大于20dp時(shí)干旁,強(qiáng)制高度變?yōu)?0dp,太高了不美觀争群。
* */
maxHeight=DisplayUtil.dip2px(getContext(),20);
if(mHeight>maxHeight) {
mHeight = maxHeight;
}
/*
* 設(shè)置高度
* */
if(mHeight>0){
heightSize=mHeight;
}
/*
* 在高度小于10dp時(shí)大年,強(qiáng)制不能使用文字顯示進(jìn)度翔试,因?yàn)楦叨葘?shí)在是太小了,在這個(gè)高度下字體看不清楚冲泥,放在進(jìn)度條外又不美觀壁涎,只好折中設(shè)計(jì)了。
* */
if(mHeight<DisplayUtil.dip2px(getContext(),10)){
showPercent=false;
}
/*
* 設(shè)置寬度
* */
if(mWidth>0){
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);
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,percentShadeColor);
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);
/*
* 依次添加第二進(jìn)度條,雙色進(jìn)度條(第一進(jìn)度條),白色漸變層流码,百分比文字顯示層等四個(gè)子View
* */
addView(progressView);
addView(colofulView);
addView(maskView);
addView(percentView);
getChildAt(0).layout(0, 0, getMeasuredWidth(), getMeasuredHeight()); //布局第二進(jìn)度條位置
int ChildHeight = getMeasuredWidth();
getChildAt(1).layout(0, -ChildHeight + getMeasuredHeight(), getMeasuredWidth(), getMeasuredWidth()); //布局雙色進(jìn)度條
/*
* 根據(jù)標(biāo)識(shí)位漫试,為雙色進(jìn)度條設(shè)置位移動(dòng)畫(無限向上移動(dòng)碘赖,視覺上達(dá)到斜條向右移動(dòng)的效果)
* */
if (animationOn) {
translateAnimation = new TranslateAnimation(0, 0, 0, ChildHeight - getMeasuredHeight());
translateAnimation.setDuration((long) (8000 * (float) getMeasuredWidth() / DisplayUtil.getScreenWidthPx(getContext())));
translateAnimation.setRepeatCount(-1);
translateAnimation.setInterpolator(new LinearInterpolator());
getChildAt(1).setAnimation(translateAnimation);
translateAnimation.start();
}
getChildAt(2).layout(0, 0, getMeasuredWidth(), getMeasuredHeight() * 2 / 3); //布局白色漸變層
getChildAt(3).layout(0, 0, textWidth,textHeight); //布局百分比文字顯示層
/*
* 根據(jù)標(biāo)志位,確定是否顯示百分比文字顯示層审编。
* */
if(showPercent){
getChildAt(3).setVisibility(VISIBLE);
}else {
getChildAt(3).setVisibility(GONE);
}
/*
* 設(shè)置默認(rèn)背景圖垒酬,你當(dāng)然也可以使用純色的資源件炉。這里我用了一個(gè)黑色透明漸變的背景斟冕,呈現(xiàn)一個(gè)由陰影效果的凹槽
* */
setBackgroundResource(R.drawable.background);
once=true;
}
}
public void showPercentText(boolean showPercent){
this.showPercent=showPercent;
}
public int getSecondProgressColor() {
return secondProgressColor;
}
public void setSecondProgressColor(int secondProgressColor) {
this.secondProgressColor = secondProgressColor;
}
public void setSecondProgressColorRes(int secondProgressColorRes) {
this.secondProgressColor = getResources().getColor(secondProgressColorRes);
}
public int getPercentColor() {
return percentColor;
}
public void setPercentColorRes(int percentColorRes) {
this.percentColor = getResources().getColor(percentColorRes);
}
public int getPercentShadeColor() {
return percentShadeColor;
}
public void setPercentShadeColor(int percentShadeColor) {
this.percentShadeColor = percentShadeColor;
}
public void setPercentShadeColorRes(int percentShadeColorRes) {
this.percentShadeColor = getResources().getColor(percentShadeColorRes);
}
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;
}
public int getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
setBackgroudColor=true;
}
public void setBackgroundColorRes(int backgroundColorRes) {
this.backgroundColor = getResources().getColor(backgroundColorRes);
setBackgroudColor=true;
}
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;
}
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(1) != null) {
int moveX = getMeasuredWidth() - (int) (partition2 * getMeasuredWidth());
getChildAt(1).setX(-moveX);
}
if (getChildAt(2) != null) {
int moveX = getMeasuredWidth() - (int) (partition2 * getMeasuredWidth());
getChildAt(2).setX(-moveX);
}
if (getChildAt(3) != null) {
if(getChildAt(1).getX()+getMeasuredWidth()>getChildAt(3).getMeasuredHeight()*2) {
getChildAt(3).setX(getChildAt(1).getX()+getMeasuredWidth()-getChildAt(3).getMeasuredHeight()*2);
}
percentView.setText((int) ((float) partition2 * 100) + "%");
/*
* 根據(jù)標(biāo)志位,確定是否顯示百分比文字顯示層伏伯。
* */
if(showPercent){
getChildAt(3).setVisibility(VISIBLE);
}else {
getChildAt(3).setVisibility(GONE);
}
}
if (!animationOn) {
if (translateAnimation != null) {
translateAnimation.cancel();
animationCancle = true;
}
} else {
if (animationCancle) {
Log.w("onDraw", "translateAnimation animationCancle");
translateAnimation.reset();
getChildAt(1).setAnimation(translateAnimation);
translateAnimation.startNow();
animationCancle = false;
}
}
if(setBackgroudColor) {
backgroundPaint.setAntiAlias(true);
backgroundPaint.setColor(backgroundColor);
canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint);
}
}
}
也是挺簡單的说搅,歡迎大家來踩呀弄唧!