-
-
Save harrane/815e8a94d7ca75d964714228af69c60c to your computer and use it in GitHub Desktop.
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); | |
} | |
} |
its not working ...
the rating is wrong.when i choose 5 , it shows only 4 stars... like that
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 .
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);
gonna crash if the progressDrawble is LayerDrawable and it layer have one instance of StateListDrawable
I've crash with SDK < 21.
I replaced
by
And it works :)
Thanks for the gist !