您的位置:首页 > 移动开发 > Android开发

Android自定义菊花进度条

2017-09-15 15:18 295 查看

先说废话

这几天要做一个跟ios一样的菊花进度条,刚开始让UI切了一张图片,然后看看怎么转起来,发现android动画里没有这样的动画,毕竟菊花的每根线是只改变透明度,不改变位置的。最后想到了自定义控件。然后UI又改了样式,这个控件用不到了,写这里保存。

这个菊花口有点大啊,没办法,ui给的要求就是这样。有没有bug我不知道,因为没有经过线上的考验,但是至少思路是这么回事。

public class LoadingProgressBar extends ProgressBar {
private static final String TAG = "LoadingProgressBar";

public LoadingProgressBar(Context context) {
super(context);
}

public LoadingProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
loadAttrs(context, attrs);
initPaint();
}

public LoadingProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}

/*view的默认宽度*/
private int mWidth;
/*view的默认高度*/
private int mHeight;
/*线条粗细*/
private int paintBold;
/*线条长度*/
private int lineLength;
/*背景线条颜色*/
private int bgPaintColor;
/*上层线条颜色*/
//    private int beforePaintColor;
/*进度文字颜色*/
private int textColor;
/*线条个数*/
private int lines;
/*背景画笔*/
private Paint bgPaint;
/*前景画笔*/
private Paint bfPaint;
/*进度文字画笔*/
private Paint textPaint;
/*当前下载进度*/
private int progress;
/*最大进度*/
private int max;
/*循环绘制*/
private int circle;
private Handler handler = new Handler();

/**
* 加载我们在attrs.xml文件的自定义的属性
*/
private void loadAttrs(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.loading_progress);
paintBold = array.getDimensionPixelSize(R.styleable.loading_progress_paintBold, 10);
lineLength = array.getDimensionPixelSize(R.styleable.loading_progress_lineLength, 25);
bgPaintColor = array.getColor(R.styleable.loading_progress_backgroundColor, Color.GRAY);
//        beforePaintColor = array.getColor(R.styleable.loading_progress_beforeColor, Color.YELLOW);
lines = array.getInt(R.styleable.loading_progress_lines, 12);
max = array.getInt(R.styleable.loading_progress_max, 100);
progress = array.getInt(R.styleable.loading_progress_progress, 0);
//        textColor = array.getColor(R.styleable.loading_progress_textColor, Color.BLACK);
array.recycle();
}

/**
* 初始化画笔
*/
private void initPaint() {
bgPaint = new Paint();
bgPaint.setColor(bgPaintColor);
bgPaint.setAntiAlias(true);
bgPaint.setStrokeWidth(paintBold);
//使得画笔更加圆滑
bgPaint.setStrokeJoin(Paint.Join.ROUND);
bgPaint.setStrokeCap(Paint.Cap.ROUND);

//        bfPaint = new Paint();
//        bfPaint.setColor(beforePaintColor);
//        bfPaint.setAntiAlias(true);
//        bfPaint.setStrokeWidth(paintBold);
//        bfPaint.setStrokeJoin(Paint.Join.ROUND);
//        bfPaint.setStrokeCap(Paint.Cap.ROUND);

//        textPaint = new Paint();
//        textPaint.setColor(textColor);
//        textPaint.setAntiAlias(true);
//        textPaint.setTextAlign(Paint.Align.CENTER);
//        textPaint.setTextSize(40);
circle = 0;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取view的宽度
mWidth = getViewSize(100, widthMeasureSpec);
//获取view的高度
mHeight = getViewSize(100, heightMeasureSpec);
}

/**
* 测量模式 表示意思
* UNSPECIFIED 父容器没有对当前View有任何限制,当前View可以任意取尺寸
* EXACTLY 当前的尺寸就是当前View应该取的尺寸
* AT_MOST 当前尺寸是当前View能取的最大尺寸
*
* @param defaultSize 默认大小
* @param measureSpec 包含测量模式和宽高信息
* @return 返回View的宽高大小
*/
private int getViewSize(int defaultSize, int measureSpec) {
int viewSize = defaultSize;
//获取测量模式
int mode = MeasureSpec.getMode(measureSpec);
//获取大小
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED: //如果没有指定大小,就设置为默认大小
viewSize = defaultSize;
break;
case MeasureSpec.AT_MOST: //如果测量模式是最大取值为size
//我们将大小取最大值,你也可以取其他值
viewSize = size;
break;
case MeasureSpec.EXACTLY: //如果是固定的大小,那就不要去改变它
viewSize = size;
break;
}
return viewSize;
}

@Override
protected void onDraw(Canvas canvas) {
//        super.onDraw(canvas);
int x = mWidth / 2;
int y = mHeight / 2;
int r = x - 5;
int alpha = 255;//范围0-255.
for (int i = 0; i < lines; i++) {//从circle到circle+2最亮,其他依次减小

//circle=0,亮2.1.0; circle =1,亮1.0.11; circle = 2,亮0.11.10; circle = 3,亮11.10.9; circle = 4,亮10.9.8;.....circle = 11,亮1.2.3
switch (circle) {
case 0:
if (i == 2 || i == 1 || i == 0) {
alpha = 255;
} else {
alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=3,亮度0.9;i=4,亮度0.8....i=11亮度0.1
}
break;
case 1:
if (i == 1 || i == 0 || i == 11) {
alpha = 255;
} else {
alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=2,亮度0.9;i=3,亮度0.8....i=10亮度0.1
}
break;
case 2:
if (i == 0 || i == 11 || i == 10) {
alpha = 255;
} else {
alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=1,亮度0.9;i=4,亮度0.8....i=11亮度0.1
}
break;
default:
if (i == 12 - circle + 0 || i == 12 - circle + 1 || i == 12 - circle + 2) {
alpha = 255;
} else {
alpha = (int) (255 * (1 - 0.1 * (i + circle - 2)));//i=1,亮度0.9;i=4,亮度0.8....i=11亮度0.1
}
break;
}

Log.e(TAG, "circle  =  " + circle + "    i=  " + i + "      ,    alpha=   " + alpha);
bgPaint.setAlpha(alpha);
canvas.drawLine(x, y - r, x, y - r + lineLength, bgPaint);
canvas.rotate(-360 / lines, x, y);
}

circle++;
if (circle == 12) {
circle = 0;
}

handler.postDelayed(runnable, 50);
}
private Runnable runnable = new Runnable() {
@Override
public void run() {
invalidate();
}
};
@Override
protected void onDetachedFromWindow() {
handler.removeCallbacks(runnable);
super.onDetachedFromWindow();

}

/**
* 为进度设置动画
* ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,
* 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。
* 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,
* 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,
* 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。
*
* @param start    开始值
* @param current  结束值
* @param duration 动画时长
*/
public void startAnimation(int start, int current, int duration) {
ValueAnimator progressAnimator = ValueAnimator.ofInt(start, current);
progressAnimator.setDuration(duration);
progressAnimator.setTarget(progress);
progressAnimator.setInterpolator(new BounceInterpolator());
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
progress = (int) animation.getAnimatedValue();
invalidate();
}
});
progressAnimator.start();
}

/*设置进度最大值*/
//    public void setMax(int max) {
//        this.max = max;
//        invalidate();
//    }

/*设置当前进度*/
//    public void setProgress(int progress) {
//        this.progress = progress;
//        invalidate();
//    }
}

//然后是使用

<com.hyphenate.easeui.widget.LoadingProgressBar
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerInParent="true"
loading_progress_:backgroundColor="#9f9c9c"
loading_progress_:lineLength="10dp"
loading_progress_:lines="12"
loading_progress_:max="100"
loading_progress_:paintBold="3dp"
loading_progress_:progress="70" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android