在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);
的时候不显示进度,请问是什么原因。急
天蓬老师2017-04-17 17:10:38
이전에 이런 문제가 발생한 적이 있습니다. 나중에 이 문제는 ListView
과 같은 컨트롤의 재사용 메커니즘과 관련이 있음이 밝혀졌지만 시스템의 Progress
을 사용하는 데는 문제가 없으므로 사용자 정의 컨트롤의 불완전한 메소드 적용으로 인해 발생합니다. 당시 내 솔루션은 시스템에서 제공하는 컨트롤을 사용한 다음 속성을 추가하는 것이었습니다.
귀하의 컨트롤에 있는 코드는 컨트롤의 기본 내용인 onSaveInstanceState
, onRestoreInstanceState
, invalidate
등이 덮어쓰여지지 않은 것으로 확인됩니다.
제가 제공하는 해결책은 다음과 같습니다. 시스템 컨트롤이 요구 사항을 충족할 때 시스템 컨트롤을 사용합니다. (CircleProgressIndicator
과 유사) 주요 기능을 재정의하여 사용해 보세요(여기에서는 위의 세 가지 기능이 모두 적용됩니다). 특히 invalidate
);
大家讲道理2017-04-17 17:10:38
컨트롤을 맞춤설정할 때 onDraw()를 덮어쓰면 표시되는 이유는 무엇인가요? 또한 ListView의 getItem에 있는 View의 재사용 메커니즘을 고려하세요.
伊谢尔伦2017-04-17 17:10:38
onLayout 메소드를 추가해 볼 수 있습니다. onMeasure와 onLayout은 일반적으로 View를 맞춤설정할 때 함께 사용됩니다.