Can't change vector drawable for a custom view during runtime

247 Views Asked by At

I have implemented a custom view which looks like a seekbar with drawable attached at end Custom Score bar. I have provided methods to change colour for progress, change width of the progress(along with the rocket icon), and change the icon itself(for different colours).

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();
}

}

now i am instantiating it in activity as:

    RocketView rv = (RocketView) findViewById(R.id.rv);
    rv.setProgressColor(getResources().getColor(R.color.colorAccent));
    rv.setProgress(100);
    rv.setIndicatorIcon(R.drawable.rocket_15);

If I don't set indicator icon in activity the icon is shown but as soon as I call the method setIndicatorIcon() the icon disappears. What am I missing?

0

There are 0 best solutions below