Clasificación de AndroidBar cambiar colores de estrella [cerrado]

141

¿Cómo puedo cambiar los colores y el tamaño de las estrellas?

d-man
fuente
Creo que tienes que crear tu propia barra de calificación personalizada si quieres hacer eso
Donal Rafferty
Me escribió una entrada de blog que describe cómo cambiar las imágenes RatingBar: kozyr.zydako.net/2010/05/23/pretty-ratingbar~~V~~singular~~3rd También muestra donde se puede especificar el tamaño de la imagen ...
Kozyr
Esperaba que esta pregunta sea para la barra de calificación multicolor como se muestra en los sitios web, no pude encontrar una para mí. Creé una implementación simple yo mismo github.com/codebreaker/coloredratingbar-android . Espero que esto ayude a alguien por ahí.
jaga

Respuestas:

26

Paso # 1: Cree su propio estilo, clonando uno de los estilos existentes (desde $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml), colocándolo en su propio proyecto styles.xmly haciendo referencia a él cuando agregue el widget a un diseño.

Paso # 2: Cree sus propios LayerDrawablerecursos XML para RatingBar, señalando las imágenes apropiadas para usar en la barra. Los estilos originales le indicarán los recursos existentes con los que puede comparar. Luego, ajuste su estilo para usar sus propios LayerDrawablerecursos, en lugar de los incorporados.

CommonsWare
fuente
1
Según el paso 2, esto no funciona para dispositivos Samsung 3 u otros, no es necesario que sea un LayerDrawable. Consulte aquí para obtener información: stackoverflow.com/questions/30266334/…
Kenny
66
Use android: progressTint = "@ color / yellow". Ver la respuesta de @superpuccio.
Vincent
2
progressTint solo se admite por encima del nivel 21 de la API
Yogesh Rathi
Esta es la mejor solución: stackoverflow.com/a/36297738/1935135
André Luiz Reis
120

Es un poco complicado en el blog mencionado, he usado una forma similar pero más simple. Necesita 3 imágenes de estrellas (red_star_full.png, red_star_half.png y red_star_empty.png) y una xml, eso es todo.

Pon estas 3 imágenes en res / drawable.

Ponga allí la siguiente 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>

y, finalmente, dígale a su definición de la barra de calificación que use esto, es decir

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

Eso es.

Alex
fuente
3
Hola Alex, probé esta solución, pero cuando trato de establecer la calificación en algo así como 1.1, 1.2, etc., se muestra como 1.5. He tomado imágenes de 3 estrellas, una vacía, la mitad llena y la otra llena. Supongo que se supone que debe interpolar entre ellos para obtener los componentes fraccionales, me pregunto si alguien más ha tenido el mismo problema o estoy haciendo algo notablemente mal.
Graham Baitson
¿Me puede decir acerca de las imágenes que deberíamos usar si las imágenes son de color y el tamaño de las imágenes no puedo resolver esto ...
Prithviraj Shiroor
1
¡Todos ven la respuesta de la actualización de 2015 a continuación! ¡Es mucho más fácil y sencillo!
Katie
Esta respuesta aún proporciona más flexibilidad sobre los diferentes estados de las estrellas.
Tom Brinkkemper
¿Por qué obtengo líneas verticales debajo de las estrellas? Intenté definir un estilo personalizado, especificando la altura, pero todavía hay líneas verticales debajo de las estrellas en mi AVD.
Aleksandar
93

Prueba esto, si solo quieres cambiar el color:

RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
Mirek Michalak
fuente
1
¿Qué PorterDuff.Mode.SRC_ATOPsignifica exactamente o qué hace?
Zapnologica
55
No funciona en API 5.0 y versiones posteriores. Necesidades:Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
zyamys
@zyamys Esto realmente apesta = (¿Es necesario un método para "versiones superiores" y otro método para versiones anteriores?
Daniela Morais
1
Solo funciona para una precisión de 0.5. De lo contrario (precisión <0.5), la superposición se vuelve extraña y parece que el color azul todavía tiene una precisión de 0.5 mientras que el amarillo es preciso
Teo Inke
1
Advertencia: se bloquea en dispositivos pre-lolipop. Ve con la respuesta aceptada.
blockwala
70

La forma más fácil que funcionó para mí ... si está extendiendo la actividad de AppCompat

En su build.gradle agregue la última biblioteca de appcompat.

dependencies {  
    compile 'com.android.support:appcompat-v7:X.X.X' // where X.X.X version
}

Haga que su actividad se extienda android.support.v7.app.AppCompatActivity

public class MainActivity extends AppCompatActivity {  
    ...
}

Declare un estilo personalizado en su archivo styles.xml.

<style name="RatingBar" parent="Theme.AppCompat">  
    <item name="colorControlNormal">@color/indigo</item>
    <item name="colorControlActivated">@color/pink</item>
</style>  

Aplique este estilo a su RatingBar a través de Android: atributo de tema.

<RatingBar  
    android:theme="@style/RatingBar"
    android:rating="3"
    android:stepSize="0.5"
    android:numStars="5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
Vishal Kumar
fuente
3
Gracias @Vishal Kumar. Lo probé en Kitkat 4.4.4 (Samsung S3 neo) y Marshmallow 6.0.1 (Samsung Galaxy On Nxt), funcionó. Pero no hubo éxito en Lollipop 5.1 (Micromax). Para Lollipop, utilicé el atributo "android: progressTint" en RatingBar y sí, funciona.
Prashant
Esa es la mejor solución.
Arhat Baid
Esta debería ser la respuesta correcta seleccionada.
Hampel Előd
1
Esta es la mejor solución. Si desea cambiar el tamaño de la estrella, pueden usarlo style="?android:ratingBarStyleSmall"juntos.
André Luiz Reis
@ AndréLuizReis <style name="RatingBarSmallTheme" parent="Theme.AppCompat"> <item name="colorControlNormal">@color/colorOrangeNormal</item> <item name="colorControlActivated">@color/colorOrangeActivated</item> <item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar.Small</item> </style> y tu calificación Bar android:theme="@style/RatingBarSmallTheme"
Zakhar Rodionov
47

Actualización 2015

Ahora puede usar DrawableCompat para teñir todo tipo de elementos dibujables. Por ejemplo:

Drawable progress = ratingBar.getProgressDrawable();
DrawableCompat.setTint(progress, Color.WHITE);

Esto es compatible con versiones anteriores hasta API 4

lgvalle
fuente
No te olvides de volver a establecer el dibujo en la barra de calificación.
exprimir
15
Esto tiñe todo el dibujo en un solo color, lo que hace que las estrellas vacías sean muy difíciles de distinguir.
blueice
Esto funciona solo con la biblioteca de soporte de Android> = 22 y no con la biblioteca de soporte <22.
Raghav Sharma
2
Dibuja 5 estrellas de colores, no 3.5.
CoolMind
1
Simplemente lo rodearía, if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}ya que funciona de manera predeterminada desde la API 22.
Yoann Hercouet
38

Desde API 21 en adelante, es muy fácil cambiar el color de las estrellas con estas tres líneas de código:

android:progressTint="@android:color/holo_red_dark"
android:progressBackgroundTint="@android:color/holo_red_dark"
android:secondaryProgressTint="@android:color/holo_red_dark" 

Haciéndolo así, cambiarás:

  • el color de las estrellas rellenas (progressTint)
  • el color de las estrellas sin llenar (progressBackgroundTint)
  • y el color del borde (secundarioProgresoTinte) de las estrellas
superpuccio
fuente
En lugar de 3.5, pinta 4 estrellas.
CoolMind
@CoolMind establece android: stepSize: 1 en lugar de 0.5
eLemEnt
44
¿Cómo cambiar el color de una estrella vacía?
winklerrr
@winklerrr, ¿encontraste una solución para cambiar el color de una estrella vacía?
Tarun Kumar
No hice más controles para encontrar una solución
winklerrr
36

Si desea cambiar el color de todas las estrellas, le digo que mi uso:

LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(getResources().getColor(R.color.starFullySelected), PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(1).setColorFilter(getResources().getColor(R.color.starPartiallySelected), PorterDuff.Mode.SRC_ATOP);
stars.getDrawable(0).setColorFilter(getResources().getColor(R.color.starNotSelected), PorterDuff.Mode.SRC_ATOP);
Yuriy Vinogradov
fuente
¿Hay alguna forma de establecer el color de las estrellas en función de los datos obtenidos de la base de datos? Digamos que obtuve 5 estrellas y los datos devueltos de la base de datos fueron 4. Entonces, en lugar de cambiar los 5, solo cambio los primeros 4
1
getColor está en desuso ahora, ¿alguna alternativa?
Manohar Reddy
2
Puede encontrar respuestas aquí stackoverflow.com/a/32202256/2513291 Por ejemplo, este enfoque ContextCompat.getColor (contexto, R.color.color_name)
Yuriy Vinogradov
funciona bien, pero tenga en cuenta que, por alguna razón, el orden es importante (2, luego 1, luego 0). Intenté lo contrario y provocó algunos problemas de interfaz de usuario la primera vez que se cambió el color.
Simon Ninon
25

Las soluciones que Alex y CommonsWares han publicado son correctas. Sin embargo, una cosa de la que Android nunca habla es el tamaño de píxeles adecuado para diferentes densidades. Aquí están las dimensiones requeridas para cada densidad basada en halo de luz.

Pequeña estrella

mdpi: 16px
hdpi: 24px
xhdpi: 32px
xxhdpi: 48px

Estrella mediana

mdpi: 24px
hdpi: 36px
xhdpi: 48px
xxhdpi: 72px

Estrella grande

mdpi: 35px
hdpi: 52px
xhdpi: 69px
xxhdpi: 105px
dirkoneill
fuente
¿Puedo usar vectordrawble con estrellas?
Mina Fawzy
24

Así que he estado luchando con este problema durante dos horas y he encontrado una solución de trabajo para todas las versiones de API, donde también se muestran las calificaciones de media estrella.

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);
    }
}

Se llama al método con este orden de elementos dibujables:

    LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
    // Filled stars
    setRatingStarColor(stars.getDrawable(2), ContextCompat.getColor(getContext(), R.color.foreground));
    // Half filled stars
    setRatingStarColor(stars.getDrawable(1), ContextCompat.getColor(getContext(), R.color.background));
    // Empty stars
    setRatingStarColor(stars.getDrawable(0), ContextCompat.getColor(getContext(), R.color.background));

NOTA: También debe especificar los atributos "max" y "numStars" en XML, de lo contrario no se mostrarán medias estrellas.

caja
fuente
la única forma que funciona para mí en API19, pero no me he rendido a buscar una manera de hacerlo solo desde xml T_T
Beeing Jk
@BeeingJk si crea una vista personalizada que extiende RatingBar, puede crear sus propios atributos xml para especificar el color del tinte. Luego tiene un único punto de control para configurar el tinte y puede especificar el tinte en xml. ¡Espero que ayude! Puede explicar más si es necesario
Forrest Bice
Mode.SRC_INo Mode.MULTIPLY?
Dr.jacky
12

Ahora puede usar DrawableCompat desde AppCompat v22.1.0 en adelante para teñir dinámicamente todo tipo de elementos dibujables, útil cuando admite varios temas con un solo conjunto de elementos dibujables. Por ejemplo:

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

Esto es compatible con versiones anteriores hasta API 4. Consulte también la publicación de blog de Chris Banes en Support Libraries v22.1.0

Para el tamaño y la forma reales, deberá definir un nuevo estilo y una lista de capas dibujables para el tamaño apropiado, ya que otros ya han respondido anteriormente.

Dan Dar3
fuente
Los elementos dibujables no son matrices, ¿cómo está accediendo al progreso [0]?
blueice
@blueice Tienes razón, lo siento, Drawable debería ser un LayerDrawable, corregido ahora, gracias.
Dan Dar3
Todavía no parecía funcionar para mí, terminé con lo que Yuriy Vinogradov respondió de manera diferente a esta pregunta y eso parece funcionar.
blueice
¿Cómo cambiar Drawable en cambio Cambiar color?
Iman Marashi
@ImanMarashi Vea la respuesta de Alex basada en XML arriba, LayerDrawable.setDrawable (indexable , drawable) solo está disponible desde API23 en adelante.
Dan Dar3
10

Utilizar android:theme atributo:

styles.xml

<style name="Theme.Rating" parent="Theme.AppCompat.Light">
    <item name="colorAccent">@color/rating</item>
</style>

layout.xml

<android.support.v7.widget.AppCompatRatingBar
    android:theme="@style/Theme.Rating"
    android:numStars="5"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
hidro
fuente
9

Por solo cambiar el color de la barra de calificación de xml: -

android:progressTint="@color/your_color"
android:backgroundTint="@color/your_color"
android:secondaryProgressTint="@color/your_color"
Rahul
fuente
no cambia el color de la estrella vacía
Nainal
7

Para cambiar el color solo tienes que configurar el parámetro android: progressTint

 <RatingBar
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginTop="15dp"
        android:numStars="5"
        android:rating="1"
        android:progressTint="@android:/color/black"
        android:layout_gravity="center"
       />

Para el tamaño de la propiedad de estilo.

letrounet
fuente
funciona solo en API 21 o superior, gracias
Junaid
5

La forma más simple:

android:progressTint="@color/color"
Mehatab
fuente
1
Tenga en cuenta que esto solo funciona en la API 21+
Ixx
4

Construyendo la respuesta de @ lgvalle.

Actualización 2015

Ahora puede usar DrawableCompat para teñir todo tipo de elementos dibujables. Por ejemplo:

Progreso dibujable = ratingBar.getProgressDrawable (); DrawableCompat.setTint (progreso, Color.WHITE); Esto es compatible con versiones anteriores hasta API 4

LayerDrawable drawable = (LayerDrawable) getProgressDrawable();
Drawable progress = drawable.getDrawable(2);
DrawableCompat.setTint(progress, getResources().getColor(COLOR1));
progress = drawable.getDrawable(1);
DrawableCompat.setTintMode(progress, PorterDuff.Mode.DST_ATOP);
DrawableCompat.setTint(progress, getResources().getColor(COLOR1));
DrawableCompat.setTintMode(progress, PorterDuff.Mode.SRC_ATOP);
DrawableCompat.setTint(progress, getResources().getColor(COLOR2));
progress = drawable.getDrawable(0);
DrawableCompat.setTint(progress, getResources().getColor(COLOR2));

Esto mantendrá los colores de los pasos de fracción.

splangi
fuente
4
<!--For rating bar -->
    <style name="RatingBarfeed" parent="Theme.AppCompat">
        <item name="colorControlNormal">@color/colorPrimary</item>
        <item name="colorControlActivated">@color/colorPrimary</item>
    </style>

usa tu propio color

Sibasish
fuente
4

Sin agregar un nuevo estilo, puede usar el color de tinte dentro del 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"/>
4ndro1d
fuente
3

Funciona para Android por debajo y por encima de la versión 21

Después de algunas investigaciones, se me ocurrió este método para establecer el tinte de fondo, el tinte de separación (por ejemplo, media estrella) y el color del tinte de estrella.

LayerDrawable layers = (LayerDrawable) ratingBar.getProgressDrawable();
DrawableCompat.setTint(layers.getDrawable(0), 0x33000000); // The background tint
DrawableCompat.setTint(layers.getDrawable(1), 0x00000000); // The gap tint (Transparent in this case so the gap doesnt seem darker than the background)
DrawableCompat.setTint(layers.getDrawable(2), 0xffFED80A); // The star tint
Arbitur
fuente
3

Solución simple, use AppCompatRatingBar y su método setProgressTintList para lograr esto, vea esta respuesta como referencia.

Kuldeep Sakhiya
fuente
Esto funcionó para mí bajo API 28 usando com.google.android.material: material: 1.1.0-alpha02
Mark Lapasa
2

Resuelvo este problema de la siguiente manera:

LayerDrawable layerDrawable = (LayerDrawable) ratingBar.getProgressDrawable();

DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(0)),
                       Color.WHITE);  // Empty star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(1)),
                       Color.YELLOW); // Partial star
DrawableCompat.setTint(DrawableCompat.wrap(layerDrawable.getDrawable(2)),
                       Color.YELLOW);
Hai Rom
fuente
Gracias funciona. Pero para la calificación fraccional, las estrellas están pintadas completamente.
CoolMind
2
RatingBar mRating=(RatingBar)findViewById(R.id.rating);
 LayerDrawable layerDrawable=(LayerDrawable)mRating.getProgressDrawable();
 layerDrawable.getDrawable(2).setColorFilter(Color.parseColor
 ("#32CD32"),    PorterDuff.Mode.SRC_ATOP);

para mí está funcionando ...

Vimesh Pk
fuente
1

Encontré una solución simple para cambiar el color de la estrella según tu tema.

Ir a este sitio: http://android-holo-colors.com/

Elige el color de tu tema y crea tus imágenes de estrellas.

Hardik4560
fuente
1

Usando las respuestas anteriores, creé un método estático rápido que puede reutilizarse fácilmente. Solo tiene como objetivo teñir el color de progreso de las estrellas activadas. Las estrellas que no están activadas permanecen grises.

    public static RatingBar tintRatingBar (RatingBar ratingBar, int progressColor)if (ratingBar.getProgressDrawable() instanceof LayerDrawable) {
        LayerDrawable progressDrawable = (LayerDrawable) ratingBar.getProgressDrawable();
        Drawable drawable = progressDrawable.getDrawable(2);
        Drawable compat = DrawableCompat.wrap(drawable);
        DrawableCompat.setTint(compat, progressColor);
        Drawable[] drawables = new Drawable[3];
        drawables[2] = compat;

        drawables[0] = progressDrawable.getDrawable(0);
        drawables[1] = progressDrawable.getDrawable(1);

        LayerDrawable layerDrawable = new LayerDrawable(drawables);

        ratingBar.setProgressDrawable(layerDrawable);

        return ratingBar;
    }
    else {
        Drawable progressDrawable =  ratingBar.getProgressDrawable();
        Drawable compat = DrawableCompat.wrap(progressDrawable);
        DrawableCompat.setTint(compat, progressColor);
        ratingBar.setProgressDrawable(compat);
        return ratingBar;
    }
}

Simplemente pase su barra de calificación y un Color usando getResources().getColor(R.color.my_rating_color)

Como puede ver, uso DrawableCompat para que sea compatible con versiones anteriores.

EDITAR: Este método no funciona en API21 (ve por qué). Terminas con una NullPointerException cuando llamas a setProgressBar. Terminé deshabilitando todo el método en API> = 21.

Para API> = 21, uso la solución SupperPuccio.

JDenais
fuente
java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperHoneycomb no se puede
enviar
1
@IshaanGarg tienes razón. Me encontré con el mismo problema y actualicé mi método. Actualicé mi código para manejar el caso. No creo que sea una versión de Android. Si usa la versión más pequeña de la barra de calificación (con style = "? Android: attr / ratingBarStyleSmall"), el elemento extraíble sigue siendo un LayoutDrawable.
JDenais
Sí, justo lo que había implementado, solo asegúrese de usar AppCompatRatingBar. Aunque no puedo obtener media estrella cuando preselecciono la calificación de XML / java. Como setRating (3.5) muestra 4 estrellas completas
Ishaan Garg
1

La barra de clasificación se usa automáticamente en tiempo de ejecución para cambiar el color en la estrella táctil.

Primero agregue estilo en el archivo app \ src \ main \ res \ values ​​\ styles.xml:

<style name="RatingBar" parent="Theme.AppCompat">
    <item name="colorControlNormal">@android:color/darker_gray</item>
    <item name="colorControlActivated">@color/com_facebook_blue</item>
</style>

Luego, su barra de calificación agrega un tema como este:

<RatingBar
   android:id="@+id/rating"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:numStars="5"
   android:stepSize="1"
   android:theme="@style/RatingBar"/>
Navadip Patel
fuente
0

1) declara este xml

<LinearLayout 
             android:layout_width="match_parent"
        android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:orientation="horizontal"
         android:paddingLeft="20dp"
         android:paddingRight="20dp"
         android:layout_marginBottom="20dp"
         android:background="#323232"
         android:gravity="center_horizontal">

       <com.example.android.custom_ratingbar.CustomRatingBar
        android:id="@+id/coloredRatingBar5"
        style="@style/coloredRatingBarStyleSmall"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"

         />
       </LinearLayout>

2) en style.xml

<style name="coloredRatingBarStyleSmall">
        <item name="indicator">false</item>
        <item name="type">small</item>
    </style>

3)

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class CustomRatingBar extends View{

    private static final String TAG="ColoredRatingBar";
    private static final int NORMAL = 0;
    private static final int SMALL = 1;

    Bitmap[] drawables;
    Bitmap progressBackground;
    Context mContext;
    private int mNumStars =9;
    private float mRating =0;
    private boolean mIndicator;
    private float slidePosition;
    private int mType;

    /**
     * A callback that notifies clients when the rating has been changed. This
     * includes changes that were initiated by the user through a touch gesture
     * or arrow key/trackball as well as changes that were initiated
     * programmatically.
     */
    public interface OnRatingBarChangeListener {

        /**
         * Notification that the rating has changed. Clients can use the
         * fromUser parameter to distinguish user-initiated changes from those
         * that occurred programmatically. This will not be called continuously
         * while the user is dragging, only when the user finalizes a rating by
         * lifting the touch.
         *
         * @param ratingBar The RatingBar whose rating has changed.
         * @param rating The current rating. This will be in the range
         *            0..numStars.
         * @param fromUser True if the rating change was initiated by a user's
         *            touch gesture or arrow key/horizontal trackbell movement.
         */
        void onRatingChanged(CustomRatingBar ratingBar, float rating, boolean fromUser);

    }

    private OnRatingBarChangeListener mOnRatingBarChangeListener;

    public CustomRatingBar(Context context) {
        this(context, null);
    }
    public CustomRatingBar(Context context, AttributeSet attrs) {
        this(context, attrs,0);//R.attr.coloredRatingBarStyle
    }

    public CustomRatingBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar,defStyle, 0);
        final boolean indicator = a.getBoolean(R.styleable.CustomRatingBar_indicator, false);
        final float rating = a.getFloat(R.styleable.CustomRatingBar_setrating, -1);
        final int type = a.getInt(R.styleable.CustomRatingBar_type, 0);
        a.recycle();

        setIndicator(indicator);
        setRating(rating);
        setType(type);
        init(context);
    }

    public int getType() {
        return mType;
    }

    public void setType(int type) {
        this.mType = type;
    }

    private void init(Context context) {
        mContext = context;
        Resources res = getResources();
        if(mType==SMALL){
            drawables = new Bitmap[]{BitmapFactory.decodeResource(res, R.drawable.rating_inactive),BitmapFactory.decodeResource(res, R.drawable.rating_active)};
            progressBackground = BitmapFactory.decodeResource(res, R.drawable.rating_inactive);
        }else{
            drawables = new Bitmap[]{BitmapFactory.decodeResource(res, R.drawable.rating_inactive),BitmapFactory.decodeResource(res, R.drawable.rating_active)};
            progressBackground = BitmapFactory.decodeResource(res, R.drawable.rating_inactive);
        }

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //draw empty stars bg
        for(int i=0;i< mNumStars;i++){
            drawStar(canvas,i);
        }

    }


    private void drawStar(Canvas canvas, int position) {
        float fraction = mRating -(position);
        Bitmap ratedStar1 = getRatedStar();
        Paint paint=getPaint(position);
        int division=getSize();
        Bitmap ratedStar=null;
        Bitmap emptyStar=null;
       if(!isInEditMode()){
        ratedStar=Bitmap.createScaledBitmap(ratedStar1, division, division, false);
        emptyStar=Bitmap.createScaledBitmap(progressBackground, division, division, false);
       }
        if((position)< mRating){
            if(!isInEditMode()){
           canvas.drawBitmap(ratedStar,(position* division),0,paint);
            }

        } else{

                if(!isInEditMode()){
              canvas.drawBitmap(emptyStar,(position*division),0,null);

            }
        }


    }
    private int getSize(){
        return (getWidth()/mNumStars);
    }

    private Bitmap getRatedStar() {

        if(mRating==0){
            return drawables[0];
        }
        else{
            return drawables[1];
        }
    }

    private Paint getPaint(int position){
        int value=(255*(position+1))/mNumStars;
        String hexString=Integer.toHexString(value).equals("0")?"00":Integer.toHexString(value);
        String hexvalue="#"+hexString+"000000";//FEE98E
        //Log.e("TAG", position+"/"+value+"/"+hexvalue);

        Paint paint=new Paint();

        paint.setColor(Color.parseColor(hexvalue));

        return paint;
    }

    public int getNumStars() {
        return mNumStars;
    }

    public void setNumStars(int numStars) {
        this.mNumStars = numStars;
    }

    public float getRating() {
        return mRating;
    }

    public void setRating(float rating) {
        setRating(rating,false);
    }

    void setRating(float rating,boolean fromUser) {
        if(rating>mNumStars){
            this.mRating = mNumStars;
        }
        this.mRating = rating;
        invalidate();
        dispatchRatingChange(fromUser);
    }

    public boolean isIndicator() {
        return mIndicator;
    }

    public void setIndicator(boolean indicator) {
        this.mIndicator = indicator;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (progressBackground != null) {

            final int width = progressBackground.getWidth() * mNumStars;
            final int height = progressBackground.getHeight();

            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            Bitmap emptyStar=Bitmap.createScaledBitmap(progressBackground, widthSize/mNumStars, widthSize/mNumStars, false);
            int heightSize = emptyStar.getHeight();

            setMeasuredDimension(resolveSizeAndState(widthSize, widthMeasureSpec, 0),
                    resolveSizeAndState(heightSize, heightMeasureSpec, 0));
        }
        else{
              int desiredWidth = 100;
            int desiredHeight = 50;

            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);

            int width;
            int height;

            //Measure Width
            if (widthMode == MeasureSpec.EXACTLY) {
                //Must be this size
                width = widthSize;
            } else if (widthMode == MeasureSpec.AT_MOST) {
                //Can't be bigger than...
                width = Math.min(desiredWidth, widthSize);
            } else {
                //Be whatever you want
                width = desiredWidth;
            }

            //Measure Height
            if (heightMode == MeasureSpec.EXACTLY) {
                //Must be this size
                height = heightSize;
            } else if (heightMode == MeasureSpec.AT_MOST) {
                //Can't be bigger than...
                height = Math.min(desiredHeight, heightSize);
            } else {
                //Be whatever you want
                height = desiredHeight;
            }

            //MUST CALL THIS
          setMeasuredDimension(resolveSizeAndState(width, widthMeasureSpec, 0),resolveSizeAndState(height, heightMeasureSpec, 0));
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(mIndicator){
            return false;
        }

        int action = event.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
                slidePosition = getRelativePosition(event.getX());

                int newRating = (int)(slidePosition>0?slidePosition+1:0) ;
                if(newRating>mNumStars){
                    newRating=mNumStars;
                }

             //   Log.e("TAG", ""+newRating);
                if (newRating != mRating) {
                    setRating(newRating,true);
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                break;
            default:
                break;
        }

        return true;
    }

    private float getRelativePosition(float x) {
        Bitmap emptyStar=Bitmap.createScaledBitmap(progressBackground, getWidth()/mNumStars, getWidth()/mNumStars, false);
        int widthSize = emptyStar.getWidth();
      //  Log.e("TAG", widthSize+"/"+x);
         float position = x / widthSize;
       position = Math.max(position, 0);
       return Math.min(position, mNumStars);
    }

    /**
     * Sets the listener to be called when the rating changes.
     *
     * @param listener The listener.
     */
    public void setOnRatingBarChangeListener(OnRatingBarChangeListener listener) {
        mOnRatingBarChangeListener = listener;
    }

    /**
     * @return The listener (may be null) that is listening for rating change
     *         events.
     */
    public OnRatingBarChangeListener getOnRatingBarChangeListener() {
        return mOnRatingBarChangeListener;
    }

    void dispatchRatingChange(boolean fromUser) {
        if (mOnRatingBarChangeListener != null) {
            mOnRatingBarChangeListener.onRatingChanged(this, getRating(),
                    fromUser);
        }
    }
}


5) then in calling activity---

CustomRatingBar coloredRatingBar5=(CustomRatingBar)findViewById(R.id.coloredRatingBar5);
        coloredRatingBar5.setOnRatingBarChangeListener(new OnRatingBarChangeListener() {

            @Override
            public void onRatingChanged(CustomRatingBar ratingBar, float rating,boolean fromUser) {
                // TODO Auto-generated method stub
                Log.e("RATING", ""+rating);

            }
        });

6) calificación activa --- tome cualquier imagen con color oscuro porque se usará como transparencia de color para diferentes calificaciones

rating_inactive: tome cualquier imagen del mismo tamaño de la imagen de arriba con fondo claro ... se usará cuando no se seleccione ninguna calificación

amit
fuente
0

Una forma muy fácil de cambiar el color del borde de las estrellas es usar el parámetro xml:

android:progressBackgroundTint=""

en la vista de ratingBar. El valor debe ser un código hexadecimal para un color.

Pau Arlandis Martinez
fuente
No sé por qué, pero parece que su método solo afecta el borde de las estrellas (el color de relleno sigue siendo el color predeterminado)
superpuccio
Ok, te perdiste algunos parámetros xml. Mira mi respuesta aquí abajo.
superpuccio 01 de
1
Tienes razón. No sé por qué estaba pensando que tenía problemas para cambiar el color del borde de la estrella (tal vez porque si el problema que tenía). Tu respuesta es más completa.
Pau Arlandis Martinez
0

Estaba buscando un método confiable para hacer esto hasta API 9 al menos. La solución "transmitir a LayerDrawble" me pareció una solución arriesgada, y cuando la probé en un teléfono Android en 2.3, lanzó correctamente pero la llamada a DrawableCompat.setTint (...) no tuvo ningún efecto.

La necesidad de cargar activos extraíbles tampoco me pareció una buena solución.

Decidí codificar mi propia solución, que es una clase que extiende AppCompatRatingBar, usando un Drawable personalizado que se encarga de dibujar las estrellas mediante programación. Funciona perfectamente para mis necesidades, lo publicaré en caso de que ayude a alguien:

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

El enlace es más fácil porque puede obtener el archivo completo directamente, pero aquí está el código completo por si acaso:

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;
        }
    }
}
androidseb
fuente
0

Respuesta un poco tardía pero espero que ayude a algunas personas.

<RatingBar
         android:id="@+id/rating"
         style="@style/Base.Widget.AppCompat.RatingBar.Small"
         android:theme="@style/WhiteRatingStar"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_below="@+id/profil_name"
         android:layout_centerHorizontal="true"
         android:layout_marginLeft="@dimen/dimen_4"
         android:rating="3" />

Y así es como se ve la WhiteRatingStar

<style name="WhiteRatingStar" parent="Base.Widget.AppCompat.RatingBar.Small">
     <item name="colorAccent">@android:color/white</item>
</style>

Con esto, las estrellas se colorearán en blanco, por ejemplo.

Martial Konvi
fuente
-1

Como implica la respuesta anterior, no es fácil cambiar el color de la barra de calificación. Las estrellas no se dibujan mediante programación, son imágenes con un tamaño fijo y gradientes de color específicos. Para cambiar el color, debe crear sus propias imágenes de estrellas con diferentes colores y luego crear su propio recurso XML dibujable y pasarlo a la clase ratingsBar usando setProgressDrawable (Drawable d) o el atributo XML android: progressDrawable.

David
fuente