Skip to content

Instantly share code, notes, and snippets.

@harrane
Created April 8, 2016 08:54
Show Gist options
  • Save harrane/815e8a94d7ca75d964714228af69c60c to your computer and use it in GitHub Desktop.
Save harrane/815e8a94d7ca75d964714228af69c60c to your computer and use it in GitHub Desktop.
A temp fix for using vector drawable with RatingBar Raw
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.support.v4.graphics.drawable.DrawableWrapper;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.RatingBar;
public class RatingBarVectorFix extends RatingBar {
private Bitmap mSampleTile;
public RatingBarVectorFix(Context context) {
this(context, null);
}
public RatingBarVectorFix(Context context, AttributeSet attrs) {
this(context, attrs, android.support.v7.appcompat.R.attr.ratingBarStyle);
}
public RatingBarVectorFix(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
LayerDrawable drawable = (LayerDrawable) tileify(getProgressDrawable(), false);
drawable.findDrawableByLayerId(android.R.id.background).setColorFilter(backgroundTintColor, PorterDuff.Mode.SRC_ATOP);
drawable.findDrawableByLayerId(android.R.id.progress).setColorFilter(progressTintColor, PorterDuff.Mode.SRC_ATOP);
setProgressDrawable(drawable);
}
/**
* Converts a drawable to a tiled version of itself. It will recursively
* traverse layer and state list drawables.
*/
private Drawable tileify(Drawable drawable, boolean clip) {
if (drawable instanceof DrawableWrapper) {
Drawable inner = ((DrawableWrapper) drawable).getWrappedDrawable();
if (inner != null) {
inner = tileify(inner, clip);
((DrawableWrapper) drawable).setWrappedDrawable(inner);
}
} else if (drawable instanceof LayerDrawable) {
LayerDrawable background = (LayerDrawable) drawable;
final int N = background.getNumberOfLayers();
Drawable[] outDrawables = new Drawable[N];
for (int i = 0; i < N; i++) {
int id = background.getId(i);
outDrawables[i] = tileify(background.getDrawable(i),
(id == android.R.id.progress || id == android.R.id.secondaryProgress));
}
LayerDrawable newBg = new LayerDrawable(outDrawables);
for (int i = 0; i < N; i++) {
newBg.setId(i, background.getId(i));
}
return newBg;
} else if (drawable instanceof BitmapDrawable) {
final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
final Bitmap tileBitmap = bitmapDrawable.getBitmap();
if (mSampleTile == null) {
mSampleTile = tileBitmap;
}
final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
shapeDrawable.getPaint().setShader(bitmapShader);
shapeDrawable.getPaint().setColorFilter(bitmapDrawable.getPaint().getColorFilter());
return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
ClipDrawable.HORIZONTAL) : shapeDrawable;
} else {
return tileify(getBitmapDrawableFromVectorDrawable(drawable), clip);
}
return drawable;
}
private BitmapDrawable getBitmapDrawableFromVectorDrawable(Drawable drawable) {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return new BitmapDrawable(getResources(), bitmap);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mSampleTile != null) {
final int width = mSampleTile.getWidth() * getNumStars();
setMeasuredDimension(ViewCompat.resolveSizeAndState(width, widthMeasureSpec, 0),
getMeasuredHeight());
}
}
private Shape getDrawableShape() {
final float[] roundedCorners = new float[]{5, 5, 5, 5, 5, 5, 5, 5};
return new RoundRectShape(roundedCorners, null, null);
}
}
@darzul
Copy link

darzul commented Jun 23, 2016

I've crash with SDK < 21.

I replaced

        } else {
            return tileify(getBitmapDrawableFromVectorDrawable(drawable), clip);
        }

by

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&  drawable instanceof VectorDrawable) {
            return tileify(getBitmapDrawableFromVectorDrawable(drawable), clip);
        }

And it works :)

Thanks for the gist !

@developerblinptcd
Copy link

its not working ...
the rating is wrong.when i choose 5 , it shows only 4 stars... like that

@lidemin
Copy link

lidemin commented Jun 7, 2017

Thanks to @darzul and it works after this change.

Also I comment these 2 lines

drawable.findDrawableByLayerId(android.R.id.background).setColorFilter(backgroundTintColor, PorterDuff.Mode.SRC_ATOP);
drawable.findDrawableByLayerId(android.R.id.progress).setColorFilter(progressTintColor, PorterDuff.Mode.SRC_ATOP);

to respect the color defined in svg xml .

@karan4c6
Copy link

I have also commented these two lines, but the rating is wrong, it selects different number of stars than it should.
For example I select 3 stars, it will select 5 sometimes or if I select 2, it will show 3 or 4 are selected..

drawable.findDrawableByLayerId(android.R.id.background).setColorFilter(backgroundTintColor, PorterDuff.Mode.SRC_ATOP);
drawable.findDrawableByLayerId(android.R.id.progress).setColorFilter(progressTintColor, PorterDuff.Mode.SRC_ATOP);

@cuong292
Copy link

cuong292 commented Jun 19, 2020

gonna crash if the progressDrawble is LayerDrawable and it layer have one instance of StateListDrawable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment