在运行时期间无法更改自定义视图的矢量drawable

时间:2017-09-08 07:12:34

标签: android android-custom-view ondraw android-vectordrawable android-view-invalidate

我已经实现了一个自定义视图,它看起来像一个在末尾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() ,图标就会消失。我错过了什么?

0 个答案:

没有答案