在ListView中我每个Item都放了一个自己定义的progress,代码如下:
public class LProgressBar extends View {
private final int DEFAULT_HEIGHT = dp2px(10);
private static final int DEFAULT_REACHED_COLOR = 0xFFE66059;
private static final int DEFAULT_UNREACHED_COLOR = 0xFF7A9B5B;
private static final int DEFAULT_ANIMATE_DURATION = 1000;
private static final int DEFAULT_MAX_VALUE = 100;
private static final int DEFAULT_PROGRESS = 0;
private static final Boolean DEBUG = false;
private int mHeight;
private int mRealWidth;
private int mReachedColor;
private int mUnreachedColor;
private int mDuration;
private float mProgress;
private int mMaxValue;
private boolean debug;
private Paint mUnreachedPaint;
private Paint mReachedPaint;
public LProgressBar(Context context) {
this(context, null);
}
public LProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
obtainStyledAttributes(attrs);
reset();
}
private void obtainStyledAttributes(AttributeSet attrs) {
final TypedArray attr = getContext().obtainStyledAttributes(attrs, R.styleable.LProgressBar);
mHeight = (int) attr.getDimension(R.styleable.LProgressBar_ruman_height, DEFAULT_HEIGHT);
mReachedColor = attr.getColor(R.styleable.LProgressBar_ruman_reached_color, DEFAULT_REACHED_COLOR);
mUnreachedColor = attr.getColor(R.styleable.LProgressBar_ruman_unreached_color, DEFAULT_UNREACHED_COLOR);
debug = attr.getBoolean(R.styleable.LProgressBar_ruman_debug, DEBUG);
mDuration = (int) attr.getDimension(R.styleable.LProgressBar_ruman_duration, DEFAULT_ANIMATE_DURATION);
mProgress = (float) attr.getFloat(R.styleable.LProgressBar_ruman_progress, DEFAULT_PROGRESS);
mMaxValue = (int) attr.getDimension(R.styleable.LProgressBar_ruman_maxvalue, DEFAULT_MAX_VALUE);
attr.recycle();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
} else {
width = 100;
if (widthMode == MeasureSpec.AT_MOST)
width = Math.min(widthSize, 100);
}
if (heightMode == MeasureSpec.EXACTLY)
height = heightSize;
else {
height = mHeight;
if (heightMode == MeasureSpec.AT_MOST)
height = Math.min(heightSize, mHeight);
}
setMeasuredDimension(width, height);
mRealWidth = getMeasuredWidth();
}
@Override
protected synchronized void onDraw(Canvas canvas) {
canvas.drawLine(0, 0, mRealWidth, 0, mUnreachedPaint);
canvas.drawLine(0, 0, mProgress, 0, mReachedPaint);
}
private void reset() {
initUnreachedPaint();
initReachedPaint();
}
private void initUnreachedPaint() {
mUnreachedPaint = new Paint();
mUnreachedPaint.setColor(mUnreachedColor);
mUnreachedPaint.setStrokeWidth(dp2px(mHeight));
}
private void initReachedPaint() {
mReachedPaint = new Paint();
mReachedPaint.setColor(mReachedColor);
mReachedPaint.setStrokeWidth(dp2px(mHeight));
}
public synchronized void setProgress(float progress) {
float radio = (float) progress * 1.0f / mMaxValue * 1.0f;
mProgress = (float) mRealWidth * radio * 1.0f;
invalidate();
// startProgressAnim();
}
private void startProgressAnim() {
ValueAnimator animator = ValueAnimator.ofFloat(0, mProgress);
animator.setDuration(mDuration);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
mProgress = value;
invalidate();
}
});
animator.start();
}
/**
* dp2px
*
* @param dpValue dp
* @return px
*/
private int dp2px(int dpValue) {
return (int) getContext().getResources().getDisplayMetrics().density * dpValue;
}
我在adapter中getView()
方法中去lProgressBar.setProgress(50.0f);
的时候不显示进度,请问是什么原因。急
ListView에 배치되지 않으면 원하는 애니메이션 효과가 정상적으로 실행될 수 있나요?
이전에 이런 문제가 발생한 적이 있습니다. 나중에 이 문제는
처리됩니다.ListView
과 같은 컨트롤의 재사용 메커니즘과 관련이 있음이 밝혀졌지만 시스템의Progress
을 사용하는 데는 문제가 없으므로 사용자 정의 컨트롤의 불완전한 메소드 적용으로 인해 발생합니다. 당시 내 솔루션은 시스템에서 제공하는 컨트롤을 사용한 다음 속성을 추가하는 것이었습니다.귀하의 컨트롤에 있는 코드는 컨트롤의 기본 내용인
onSaveInstanceState
,onRestoreInstanceState
,invalidate
등이 덮어쓰여지지 않은 것으로 확인됩니다.제가 제공하는 해결책은 다음과 같습니다. 시스템 컨트롤이 요구 사항을 충족할 때 시스템 컨트롤을 사용합니다. (
CircleProgressIndicator
과 유사) 주요 기능을 재정의하여 사용해 보세요(여기에서는 위의 세 가지 기능이 모두 적용됩니다). 특히invalidate
);컨트롤을 맞춤설정할 때 onDraw()를 덮어쓰면 표시되는 이유는 무엇인가요? 또한 ListView의 getItem에 있는 View의 재사용 메커니즘을 고려하세요.
onLayout 메소드를 추가해 볼 수 있습니다. onMeasure와 onLayout은 일반적으로 View를 맞춤설정할 때 함께 사용됩니다.