我已经实现了一个自定义视图,它看起来像一个在末尾Custom Score bar附加了drawable的搜索栏。我提供了改变进度颜色的方法,改变进度的宽度(以及火箭图标),并更改图标本身(针对不同的颜色)。
public class RocketView extends View {
private int mProgressWidth = 12;
private Drawable mIndicatorIcon;
private int mProgress, mMin = 0, mMax = 100;
private Paint mBackgroundPaint, mProgressPaint;
private RectF mBackgroundRect = new RectF();
private RectF mProgressRect = new RectF();
private int mIndicatorSize;
private int mProgressColor;
private int mIndicatorLeft;
public RocketView(Context context) {
super(context);
init(context, null);
}
public RocketView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
void init(Context context, AttributeSet attrs) {
float density = getResources().getDisplayMetrics().density;
int backgroundColor = ContextCompat.getColor(context, R.color.color_bg);
int progressColor = ContextCompat.getColor(context, R.color.color_progress);
mProgressWidth = (int) (mProgressWidth * density);
mIndicatorIcon = ContextCompat.getDrawable(context, R.drawable.rocket_15);
if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RocketView, 0, 0);
Drawable indicatorIcon = a.getDrawable(R.styleable.RocketView_indicatorIcon);
if (indicatorIcon != null) mIndicatorIcon = indicatorIcon;
mProgress = a.getInteger(R.styleable.RocketView_progress, 0);
mProgressWidth = (int) a.getDimension(R.styleable.RocketView_thickness, mProgressWidth);
mIndicatorSize = 10*mProgressWidth;
mIndicatorIcon.setBounds(0, 0, mIndicatorSize, mIndicatorSize);
mProgressColor = a.getColor(R.styleable.RocketView_progressColor, progressColor);
backgroundColor = a.getColor(R.styleable.RocketView_backgroundColor, backgroundColor);
a.recycle();
}
// range check
mProgress = (mProgress > mMax) ? mMax : mProgress;
mProgress = (mProgress < mMin) ? mMin : mProgress;
mBackgroundPaint = new Paint();
mBackgroundPaint.setColor(backgroundColor);
mBackgroundPaint.setAntiAlias(true);
mBackgroundPaint.setStyle(Paint.Style.STROKE);
mBackgroundPaint.setStrokeWidth(mProgressWidth);
mBackgroundPaint.setStrokeCap(Paint.Cap.ROUND);
mProgressPaint = new Paint();
mProgressPaint.setColor(mProgressColor);
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mProgressPaint.setStrokeWidth(mProgressWidth);
mProgressPaint.setStrokeCap(Paint.Cap.ROUND);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
int top = 0;
int left = 0;
//normalizing the value from 0 to 100 to 0 to container width
/* Formula for linear range [A..B] to [C..D],
*
* (D-C)*(X-A)
X' = ----------- + C
(B-A)
*/
int extraOffset = dpToPx(2);
int extraPadding = dpToPx(8);
int x = (width - left)*(mProgress - 0)/(100 -0) + 0;
top = 2*mIndicatorSize/5 + mProgressWidth/2 +extraOffset;
mBackgroundRect.set(left +extraPadding, top, left + width -extraPadding, top+mProgressWidth/2 );
int indicatorLeft = width - (left + x);
if (indicatorLeft < mIndicatorSize) {
mIndicatorLeft = width - mIndicatorSize;
mProgressRect.set(left +extraPadding, top, left + x - dpToPx(20), top + mProgressWidth/2 );
}
else {
mIndicatorLeft = left + x - dpToPx(16);
mProgressRect.set(left +extraPadding, top, left + x, top + mProgressWidth/2);
}
setMeasuredDimension(width, mIndicatorSize);
}
@Override
protected void onDraw(Canvas canvas) {
// draw the background
canvas.drawRoundRect(mBackgroundRect, mProgressWidth/2, mProgressWidth/2, mBackgroundPaint);
//draw progress
canvas.drawRoundRect(mProgressRect, mProgressWidth/2, mProgressWidth/2, mProgressPaint);
// draw the indicator icon
canvas.translate(mIndicatorLeft,0);
mIndicatorIcon.draw(canvas);
}
public static int dpToPx(int dp){
return dp * (Resources.getSystem().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public void setIndicatorIcon(int indicatorIcon) {
mIndicatorIcon = getResources().getDrawable(indicatorIcon);
invalidate();
}
public void setProgress(int progress) {
mProgress = progress;
invalidate();
}
public void setProgressColor(int color) {
mProgressColor = color;
mProgressPaint = new Paint();
mProgressPaint.setColor(mProgressColor);
mProgressPaint.setAntiAlias(true);
mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mProgressPaint.setStrokeWidth(mProgressWidth);
invalidate();
}
}
现在我在活动中将其实例化为:
RocketView rv = (RocketView) findViewById(R.id.rv);
rv.setProgressColor(getResources().getColor(R.color.colorAccent));
rv.setProgress(100);
rv.setIndicatorIcon(R.drawable.rocket_15);
如果我没有在活动中设置指示符图标,则会显示图标,但只要我调用方法 setIndicatorIcon() ,图标就会消失。我错过了什么?