Android RatingBar change star colors [closed]

2019-01-03 04:07发布

How can i change the star colors and how can i change the size of the stars ?

30条回答
可以哭但决不认输i
2楼-- · 2019-01-03 05:01

Withou adding a new style you can use the tint color within the RatingBar

             <RatingBar
                    android:id="@+id/ratingBar"
                    style="@android:style/Widget.Holo.RatingBar.Small"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:numStars="5"
                    android:rating="4.5"
                    android:stepSize="0.5"
                    android:progressTint="@color/colorPrimary"/>
查看更多
家丑人穷心不美
3楼-- · 2019-01-03 05:02

A very easy way to change the border colour of the stars is using the xml parameter:

android:progressBackgroundTint=""

in the ratingBar view. The value should be a hexadecimal code for a color.

查看更多
戒情不戒烟
4楼-- · 2019-01-03 05:02

I was looking for a reliable method to do this all the way down to API 9 at least. The "casting to LayerDrawble" solution seemed like a risky solution to me, and when I tested it out on an Android phone on 2.3, it casted successfully but the call to DrawableCompat.setTint(...) did not have any effect.

The need to load drawable assets did not seem like a good solution to me either.

I decided to code my own solution which is a class extending AppCompatRatingBar, using a custom Drawable taking care of drawing the stars programmatically. It works perfectly for my needs, I'll post it in case it helps anyone:

https://gist.github.com/androidseb/2b8044c90a07c7a52b4bbff3453c8460

The link is easier because you can get the full file directly, but here is the full code just in case:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatRatingBar;
import android.util.AttributeSet;

/**
 * @author androidseb
 *         <p/>
 *         Extends AppCompatRatingBar with the ability to tint the drawn stars when selected, pressed and un-selected.
 *         Limitation: Only draws full stars.
 */
public class TintableRatingBar extends AppCompatRatingBar {
    private TintableRatingBarProgressDrawable progressDrawable;

    public TintableRatingBar(final Context context) {
        super(context);
        init();
    }

    public TintableRatingBar(final Context context, final AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public TintableRatingBar(final Context context, final AttributeSet attrs, final int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        progressDrawable = new TintableRatingBarProgressDrawable();
        setProgressDrawable(progressDrawable);
    }

    public void setCustomTintColors(final int _uncheckedColor, final int _pressedColor, final int _checkedColor) {
        progressDrawable.setRatingMaxLevelValue(getMax() * 1000);
        progressDrawable.setUnCheckedColor(_uncheckedColor);
        progressDrawable.setPressedColor(_pressedColor);
        progressDrawable.setCheckedColor(_checkedColor);
        invalidate();
    }

    public class TintableRatingBarProgressDrawable extends Drawable {
        private static final int STAR_COUNT = 5;
        private static final int STAR_BRANCHES_COUNT = 5;

        /** Sets the max level value: if the level is at the max, then all stars are selected. */
        private int ratingMaxLevelValue = 10000;
        /** Color to be painted for unselected stars */
        private int uncheckedColor = Color.GRAY;
        /** Color to be painted for unselected stars when the ratingbar is pressed */
        private int pressedColor = Color.CYAN;
        /** Color to be painted for selected stars */
        private int checkedColor = Color.BLUE;

        @Override
        public void setAlpha(final int _i) {
        }

        @Override
        public void setColorFilter(final ColorFilter _colorFilter) {
        }

        @Override
        public boolean isStateful() {
            return true;
        }

        @Override
        public boolean setState(final int[] stateSet) {
            final boolean res = super.setState(stateSet);
            invalidateSelf();
            return res;
        }

        @Override
        public int getOpacity() {
            return 255;
        }

        public void setRatingMaxLevelValue(final int _ratingMaxLevelValue) {
            ratingMaxLevelValue = _ratingMaxLevelValue;
        }

        public void setUnCheckedColor(final int _uncheckedColor) {
            uncheckedColor = _uncheckedColor;
        }

        public void setPressedColor(final int _pressedColor) {
            pressedColor = _pressedColor;
        }

        public void setCheckedColor(final int _checkedColor) {
            checkedColor = _checkedColor;
        }

        @Override
        public void draw(final Canvas _canvas) {
            boolean pressed = false;
            for (int i : getState()) {
                if (i == android.R.attr.state_pressed) {
                    pressed = true;
                }
            }

            final int level = (int) Math.ceil(getLevel() / (double) ratingMaxLevelValue * STAR_COUNT);
            final int starRadius = Math.min(getBounds().bottom / 2, getBounds().right / STAR_COUNT / 2);

            for (int i = 0; i < STAR_COUNT; i++) {
                final int usedColor;
                if (level >= i + 1) {
                    usedColor = checkedColor;
                } else if (pressed) {
                    usedColor = pressedColor;
                } else {
                    usedColor = uncheckedColor;
                }
                drawStar(_canvas, usedColor, (i * 2 + 1) * starRadius, getBounds().bottom / 2, starRadius,
                    STAR_BRANCHES_COUNT);
            }
        }

        private void drawStar(final Canvas _canvas, final int _color, final float _centerX, final float _centerY,
            final float _radius, final int _branchesCount) {
            final double rotationAngle = Math.PI * 2 / _branchesCount;
            final double rotationAngleComplement = Math.PI / 2 - rotationAngle;
            //Calculating how much space is left between the bottom of the star and the bottom of the circle
            //In order to be able to center the star visually relatively to the square when drawn
            final float bottomOffset = (float) (_radius - _radius * Math.sin(rotationAngle / 2) / Math.tan(
                rotationAngle / 2));
            final float actualCenterY = _centerY + (bottomOffset / 2);
            final Paint paint = new Paint();
            paint.setColor(_color);
            paint.setStyle(Style.FILL);
            final Path path = new Path();
            final float relativeY = (float) (_radius - _radius * (1 - Math.sin(rotationAngleComplement)));
            final float relativeX = (float) (Math.tan(rotationAngle / 2) * relativeY);
            final PointF a = new PointF(-relativeX, -relativeY);
            final PointF b = new PointF(0, -_radius);
            final PointF c = new PointF(relativeX, -relativeY);
            path.moveTo(_centerX + a.x, actualCenterY + a.y);
            _canvas.save();
            for (int i = 0; i < _branchesCount; i++) {
                path.lineTo(_centerX + b.x, actualCenterY + b.y);
                path.lineTo(_centerX + c.x, actualCenterY + c.y);
                rotationToCenter(b, rotationAngle);
                rotationToCenter(c, rotationAngle);
            }
            _canvas.drawPath(path, paint);
            _canvas.restore();
        }

        private void rotationToCenter(final PointF _point, final double _angleRadian) {
            final float x = (float) (_point.x * Math.cos(_angleRadian) - _point.y * Math.sin(_angleRadian));
            final float y = (float) (_point.x * Math.sin(_angleRadian) + _point.y * Math.cos(_angleRadian));
            _point.x = x;
            _point.y = y;
        }
    }
}
查看更多
叛逆
5楼-- · 2019-01-03 05:03

It's a little complicated at the mentioned blog, I've used a similar but simplier way. You do need 3 star images (red_star_full.png, red_star_half.png and red_star_empty.png) and one xml, that's all.

Put these 3 images at res/drawable.

Put there the following ratingbar_red.xml:

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background" android:drawable="@drawable/red_star_empty" />
    <item android:id="@android:id/secondaryProgress" android:drawable="@drawable/red_star_half" />
    <item android:id="@android:id/progress" android:drawable="@drawable/red_star_full" />
</layer-list>

and, finally, tell your ratingbar definition to use this, i.e.

<RatingBar android:progressDrawable="@drawable/ratingbar_red"/>

That's it.

查看更多
聊天终结者
6楼-- · 2019-01-03 05:03

For just changing the color of Rating bar from xml:-

android:progressTint="@color/your_color"
android:backgroundTint="@color/your_color"
android:secondaryProgressTint="@color/your_color"
查看更多
劫难
7楼-- · 2019-01-03 05:04

Now you can use DrawableCompat from AppCompat v22.1.0 onwards to dynamically tint all kind of drawables, useful when you're supporting multiple themes with a single set of drawables. For example:

LayerDrawable layerDrawable = (LayerDrawable) ratingBar.getProgressDrawable();
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(0)), Color.RED);   // Empty star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(1)), Color.GREEN); // Partial star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(2)), Color.BLUE);  // Full star

This is backwards compatible down to API 4. Also see Chris Banes' blog post on Support Libraries v22.1.0

For the actual size and shape you will need to define a new style and layer-list drawables for the appropriate size, as others have already answered above.

查看更多
登录 后发表回答