Created
April 8, 2016 08:54
-
-
Save harrane/815e8a94d7ca75d964714228af69c60c to your computer and use it in GitHub Desktop.
A temp fix for using vector drawable with RatingBar Raw
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks to @darzul and it works after this change.
Also I comment these 2 lines
to respect the color defined in svg xml .