我有一个课程进度条。根据设置值,使用不同的颜色部分填充文本。我希望当我改变当前值时,进度填充在一段时间内从一个值平滑地进行到另一个值,而不是像现在那样通过跳跃。我怎样才能做到这一点? 我的TextProgressBar代码如下:
package com.example.app.customviews;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Shader;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.widget.TextView;
import com.example.app.R;
public class TextProgressBar extends TextView {
private final int minValue = 0;
private int maxValue = 100;
private int currentValue = 0;
private float onePercentLenght = 1;
private int[] colors = {Color.WHITE, Color.BLACK};
private float[] pos = {0,1};
public TextProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.TextProgressBar,
0, 0);
try {
maxValue = a.getInt(R.styleable.TextProgressBar_MaxProgress, 100);
currentValue = a.getInteger(R.styleable.TextProgressBar_CurrentProgress, 0);
colors[0] = a.getColor(R.styleable.TextProgressBar_ProgressColor, Color.WHITE);
colors[1] = a.getColor(R.styleable.TextProgressBar_MainColor, Color.BLACK);
} finally {
a.recycle();
}
initShader();
}
public TextProgressBar(Context context) {
super(context);
initShader();
}
@Override
protected void onDraw(Canvas canvas) {
onePercentLenght = getWidth() / maxValue;
super.onDraw(canvas);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
initShader();
}
public void setProgress(int progress) {
if(progress < minValue) {
currentValue = minValue;
}
else if( progress > maxValue) {
currentValue = maxValue;
}
else {
currentValue = progress;
}
initShader();
invalidate();
}
public void setMaxProgress(int progress) {
if(progress>minValue) {
maxValue = progress;
}
else {
maxValue = minValue;
}
invalidate();
}
public int getMaxProgress() {
return maxValue;
}
public int getProgress() {
return currentValue;
}
private void initShader() {
float x = 0, dx = (currentValue+1) * onePercentLenght;
if(dx < 0) {
dx = 0;
}
if(dx - 1 < 0) {
x = 0;
}
else {
x = dx - 1;
}
Shader textShader = new LinearGradient(x, 0, dx, 0, colors, pos, TileMode.CLAMP);
getPaint().setShader(textShader);
}
}
答案 0 :(得分:0)
我按照以下方式测试了以下方法:
10,30,延迟150ms,40延迟250ms,80延迟50ms,100延迟450ms。一个奇怪的事情是,虽然日志打印是准时的,但看起来绘图有点延迟,不确定这是否与我的设备有关。但这可以给你一些开始。根据您设置进度的频率,调整MAX_INTERVAL_TIME
可以使其更顺畅。如果回调是你从网络获得的东西,那么几乎可以让它完全顺利,因为你无法预测进展。
private static final int MAX_INTERVAL_TIME = 500;
private CountDownTimer mCountDownTimer;
public void setProgress(final int progress) {
final int startWidth = currentValue == maxValue ? 0 : currentValue;
final int endWidth = (int) (maxValue * ((float) progress / maxValue));
if (progress < minValue) {
currentValue = minValue;
} else if (progress > maxValue) {
currentValue = maxValue;
} else {
currentValue = progress;
}
if (mCountDownTimer != null) {
mCountDownTimer.cancel();
}
mCountDownTimer = new CountDownTimer(MAX_INTERVAL_TIME, 10) {
@Override
public void onTick(long millisUntilFinished) {
float interpolatedTime = 1 - ((float) millisUntilFinished / MAX_INTERVAL_TIME);
currentValue = startWidth
+ ((int) ((endWidth - startWidth) * interpolatedTime));
initShader();
invalidate();
}
@Override
public void onFinish() {
if (progress == maxValue) {
currentValue = maxValue;
initShader();
invalidate();
}
}
}.start();
}
如果您知道自己想要为进度设置动画的时间,可以尝试使用现有代码:
final TextProgressBar text = (TextProgressBar) getView().findViewById(
R.id.test);
final int animTime = 1000;
new CountDownTimer(animTime, 200) {
@Override
public void onTick(long millisUntilFinished) {
float progress = (1 - ((float) millisUntilFinished / (float) animTime))
* text.getMaxProgress();
text.setProgress((int) progress);
}
@Override
public void onFinish() {
text.setProgress(text.getMaxProgress());
}
}.start();