androidratingbarshapedrawable

ShapeDrawable as progressDrawable for RatingBar in Android?


It seems I cannot set ShapeDrawable as progressDrawable for Ratingbar. I tried the following but failed:

<RatingBar
android:id="@+id/ratingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:numStars="5"
android:stepSize="1.0"
android:rating="3.0"
style="@style/myRatingBar"
/>

myRatingbar style:

<style name="myRatingBar" parent="@android:style/Widget.RatingBar">
<item name="android:progressDrawable">@drawable/ratingbar_full</item>
<item name="android:indeterminateDrawable">@drawable/ratingbar_full</item>
<item name="android:minHeight">48dip</item>
<item name="android:maxHeight">48dip</item>
<item name="android:scaleType">center</item>
</style>

ratingbar_full.xml:

    <shape 
       android:shape="ring"
       android:innerRadius="10dip"
       android:thickness="1dip">
       <solid android:color="@color/red" />
       <size
           android:width="48dip"
           android:height="48dip"
       />
    </shape>

Nothing shows on screen.

EDIT: use .png instead of shape works for this line:

@drawable/ratingbar_full


Solution

  • I customized the @ChrisJenkins method, so you can set the size of the RatingBar icons and custom tint colors for rating images. You can set padding on your RatingBar or set your custom width and height. @ChrisJenkins solution helped me a lot to finally come up with a totally customizable RatingBar. You can set the parameters in your XML also.

    public class DrawableRatingBar extends RatingBar
    {
    // TileBitmap to base the width and hight off of.
    @Nullable
    private Bitmap iconTile;
    private float scaleIconFactor;
    private @ColorInt int iconBackgroundColor;
    private @ColorInt int iconForegroundColor;
    private @DrawableRes int iconDrawable;
    
    public DrawableRatingBar(Context context)
    {
        super(context);
        init();
    }
    
    public DrawableRatingBar(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DrawableRatingBarItem);
        scaleIconFactor = a.getFloat(R.styleable.DrawableRatingBarItem_scaleIconFactor, 1);
        iconBackgroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconBackgroundColor, Color.BLACK);
        iconForegroundColor = a.getColor(R.styleable.DrawableRatingBarItem_iconForegroundColor, Color.WHITE);
        iconDrawable = a.getResourceId(R.styleable.DrawableRatingBarItem_iconDrawable, -1);
        a.recycle();
    
        init();
    }
    
    public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
        init();
    }
    
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public DrawableRatingBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }
    
    private void init()
    {
        setProgressDrawable(createProgressDrawable());
    }
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
        if (iconTile != null)
        {
            final int width = iconTile.getWidth() * getNumStars();
            final int height = iconTile.getHeight();
            setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),
                                 resolveSizeAndState(height, heightMeasureSpec, 0));
        }
    }
    
    protected LayerDrawable createProgressDrawable()
    {
        final Drawable backgroundDrawable = createBackgroundDrawableShape();
        LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] {backgroundDrawable,
                                                                        backgroundDrawable,
                                                                        createProgressDrawableShape()});
        layerDrawable.setId(0, android.R.id.background);
        layerDrawable.setId(1, android.R.id.secondaryProgress);
        layerDrawable.setId(2, android.R.id.progress);
        return layerDrawable;
    }
    
    protected Drawable createBackgroundDrawableShape()
    {
        Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable);
    
        final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconBackgroundColor);
        if (iconTile == null)
        {
            iconTile = tileBitmap;
        }
        final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
        final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        shapeDrawable.getPaint().setShader(bitmapShader);
    
        return shapeDrawable;
    }
    
    
    private void setRatingStarColor(Drawable drawable, @ColorInt int color)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
        {
            DrawableCompat.setTint(drawable, color);
        }
        else
        {
            drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        }
    }
    
    protected Drawable createProgressDrawableShape()
    {
        Drawable drawable = ContextCompat.getDrawable(getContext(), iconDrawable);
    
        final Bitmap tileBitmap = scaleImageWithColor(drawable, scaleIconFactor, iconForegroundColor);
        final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());
        final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
        shapeDrawable.getPaint().setShader(bitmapShader);
        return new ClipDrawable(shapeDrawable, Gravity.LEFT, ClipDrawable.HORIZONTAL);
    }
    
    Shape getDrawableShape()
    {
        return new RectShape();
    }
    
    public Bitmap scaleImageWithColor(Drawable drawable, float scaleFactor, @ColorInt int color)
    {
        Bitmap b = ((BitmapDrawable) drawable).getBitmap();
    
        int sizeX = Math.round(drawable.getIntrinsicWidth() * scaleFactor);
        int sizeY = Math.round(drawable.getIntrinsicHeight() * scaleFactor);
    
        Bitmap bitmapResized = Bitmap.createScaledBitmap(b, sizeX, sizeY, true);
    
        Canvas canvas = new Canvas(bitmapResized);
        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
        paint.setAntiAlias(true);
        ColorFilter filter = new LightingColorFilter(color, 1);
        paint.setColorFilter(filter);
        canvas.drawBitmap(bitmapResized, 0, 0, paint);
    
        return bitmapResized;
    
    }
    
    protected Bitmap fromDrawable(final Drawable drawable, final int height, final int width) {
        final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }
    
    public float getScaleIconFactor() {
        return scaleIconFactor;
    }
    
    public void setScaleIconFactor(float scaleIconFactor) {
        this.scaleIconFactor = scaleIconFactor;
    }
    
    public int getIconForegroundColor() {
        return iconForegroundColor;
    }
    
    public void setIconForegroundColor(int iconForegroundColor) {
        this.iconForegroundColor = iconForegroundColor;
    }
    
    public int getIconBackgroundColor() {
        return iconBackgroundColor;
    }
    
    public void setIconBackgroundColor(int iconBackgroundColor) {
        this.iconBackgroundColor = iconBackgroundColor;
    }
    
    public int getIconDrawable() {
        return iconDrawable;
    }
    
    public void setIconDrawable(int iconDrawable) {
        this.iconDrawable = iconDrawable;
    }
    
    }
    

    Custom attributes:

    <declare-styleable name="DrawableRatingBarItem">
        <attr name="scaleIconFactor" format="float"/>
        <attr name="iconBackgroundColor" format="color"/>
        <attr name="iconForegroundColor" format="color"/>
        <attr name="iconDrawable" format="reference"/>
    </declare-styleable>