Рейтинг AndroidБар міняє кольори зірок [закрито]


141

Як я можу змінити кольори зірок і розмір зірок?


Я думаю, що вам потрібно створити власну базу рейтингу, якщо ви хочете це зробити
Donal Rafferty

Я написав повідомлення в блозі, в якому описував, як змінити зображення RatingBar: kozyr.zydako.net/2010/05/23/pretty-ratingbar У ньому також показано, де можна вказати розмір зображення ...
kozyr

Я сподівався, що це запитання для різнокольорової рейтингової панелі, як показано на веб-сайтах, не вдалося знайти собі. Створив просту реалізацію сам github.com/codebreaker/coloredratingbar-android . Сподіваюся, це допомагає комусь там.
jaga

Відповіді:


26

Крок №1: Створіть свій власний стиль, клонувавши один із існуючих стилів (від $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml), розмістивши його у власному проекті styles.xmlта посилаючись на нього, коли ви додаєте віджет у макет.

Крок №2: Створіть власні LayerDrawableXML-ресурси для RatingBar, вказуючи на відповідні зображення, які використовуються для панелі. Оригінальні стилі вкажуть на наявні ресурси, з якими можна порівняти. Потім налаштуйте свій стиль, щоб використовувати власні LayerDrawableресурси, а не вбудовані.


1
Згідно з кроком №2, це не працює для пристроїв Samsung 3 або деяких інших, це не потрібно, щоб бути LayerDrawable. Дивіться тут інформацію: stackoverflow.com/questions/30266334/…
Кенні

6
Використовуйте android: progressTint = "@ color / yellow". Дивіться відповідь @superpuccio.
Вінсент

2
progressTint підтримується лише вище рівня 21 api
Йогеш Ратхі


120

У згаданому блозі це трохи складно, я використовував подібний, але простіший спосіб. Вам потрібні три зіркові зображення (red_star_full.png, red_star_half.png і red_star_empty.png) і один xml, і це все.

Розмістіть ці 3 зображення на res / drawable.

Помістіть туди такий рейтинг bar_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>

і, нарешті, підкажіть своє визначення рейтингової панелі, щоб використовувати це, тобто

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

Це воно.


3
Привіт Алекс, я спробував це рішення, але коли я намагаюся встановити рейтинг на зразок 1.1, 1.2 і т. Д. ... його показ відображається як 1,5. Я зробив 3 зіркових зображення, одне порожнє, половину повне і одне повне. Я припускаю, що це має бути інтерпольовано між ними, щоб отримати дробові компоненти, мені просто цікаво, чи хтось інший мав ту саму проблему чи я роблю щось помітно не так?
Грехем Байтсон

Чи можете ви, будь ласка, розкажіть мені про зображення, якими ми повинні користуватися погодою, це кольорові зображення та розмір зображень, які я не в змозі вирішити ...
Prithviraj Shiroor

1
Усі бачать, що відповідь оновлення 2015 року нижче! Це набагато простіше і простіше!
katie

Ця відповідь все ще забезпечує більшу гнучкість щодо різних станів зірок.
Том Брінккепер

Чому я отримую вертикальні лінії нижче зірок? Я спробував визначити власний стиль, вказавши висоту, але все ще є вертикальні лінії нижче зірок на моєму AVD.
Олександр

93

Спробуйте це, якщо ви хочете лише змінити колір:

RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);

1
Що саме PorterDuff.Mode.SRC_ATOPозначає чи робити?
Zapnologica

5
Не працює в API 5.0 і новіших версіях. Потреби:Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
зяміс

@zyamys Це справді відстійно = (Необхідний метод для "більш високих версій" та потрібен інший метод для старих версій?
Даніела Мораїс

1
Він працює лише з точністю до 0,5. В іншому випадку (точність <0,5) накладка стає дивною і здається, що синій колір все ще є з точністю 0,5, а жовтий - точним
Teo Inke

1
Попередження: Збої на пристроях, що попередньо перебувають у стані. Ідіть із прийнятою відповіддю.
blockwala

70

Найпростіший спосіб, який працював для мене ... якщо ви розширюєте AppCompat Activity

Додайте до свого build.gradle останню бібліотеку додатків.

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

Зробіть свою діяльність розширити android.support.v7.app.AppCompatActivity

public class MainActivity extends AppCompatActivity {  
    ...
}

Заявіть про нестандартний стиль у файлі styles.xml.

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

Застосуйте цей стиль до рейтингу RatingBar через атрибут теми android:.

<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"/>

3
Дякую @Vishal Kumar Я спробував це на Kitkat 4.4.4 (Samsung S3 neo) та Marshmallow 6.0.1 (Samsung Galaxy On Nxt), це спрацювало. Але успіху на Lollipop 5.1 (Micromax) немає. Для Lollipop я використав атрибут "android: progressTint" в RatingBar, і так, він працює.
Прашант

Це найкраще рішення.
Архат Байд

Це має бути обрана правильна відповідь.
Hampel Előd

1
Це найкраще рішення. Якщо ви хочете змінити розмір зірки, ви можете використовувати style="?android:ratingBarStyleSmall"разом.
Андре Луїз Рейс

@ 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> та ваш рейтингБар android:theme="@style/RatingBarSmallTheme"
Захар Родіонов

47

Оновлення 2015 року

Тепер ви можете використовувати DravableCompat для тонування всіх видів малюнків. Наприклад:

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

Це назад сумісний з API 4


Не забудьте встановити оцінку назад на рейтинговій шкалі.
віджимання

15
Це відтіняє весь малюнок в один колір, що робить порожні зірки дуже важкими для розрізнення.
blueice

Це працює лише з бібліотекою підтримки для Android> = 22, а не з бібліотекою підтримки <22.
Рагхав Шарма

2
Він малює 5 кольорових зірок, а не 3,5.
CoolMind

1
Я просто оточую це тим, що if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}він працює за замовчуванням від API 22.
Yoann Hercouet

38

З API 21 дуже просто змінити колір зірок за допомогою цих трьох рядків коду:

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

Роблячи це так, ви зміните:

  • колір заповнених зірок (progressTint)
  • колір незаповнених зірок (progressBackgroundTint)
  • і колір межі (вториннийProgressTint) зірок

Замість 3,5 він малює 4 зірки.
CoolMind

@CoolMind встановив android: stepSize: 1 замість 0,5
eLemEnt

4
Як змінити колір порожньої зірки?
winklerrr

@winklerrr Ви знайшли рішення, як змінити колір порожньої зірки.
Тарун Кумар

Не робив додаткових перевірок, щоб знайти рішення
winklerrr

36

Якщо ви хочете змінити колір для всіх зірок, ви заявляєте:

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

Чи є способи встановити колір зірок на основі даних, отриманих із бази даних? Скажімо, я отримав 5 зірок, а дані, повернуті з бази даних, були 4. Тож замість зміни всіх 5 я змінив лише перші 4

1
getColor зараз застарілий, будь-яка альтернатива?
Манохар Редді

2
Ви можете знайти відповіді тут stackoverflow.com/a/32202256/2513291 Наприклад цей підхід ContextCompat.getColor (контекст, R.color.color_name)
Юрій Виноградов

працює добре, але зауважте, що чомусь важливий порядок (2, потім 1, потім 0). Я спробував реверс, і це призвело до деяких збоїв в інтерфейсі при першому зміні кольору.
Саймон Нінон

25

Рішення, які розмістили Alex та CommonsWares, є правильними. Одна річ, про яку Android ніколи не говорить, хоча це належні розміри пікселів для різної щільності. Ось необхідні розміри для кожної щільності на основі ореолу.

Мала зірка

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

Середня зірка

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

Велика зірка

mdpi: 35px
hdpi: 52px
xhdpi: 69px
xxhdpi: 105px

чи можу я користуватися вектором з зірками
Міна Фаузі

24

Тому я боровся з цією проблемою дві години, і я придумав робоче рішення для всіх версій API, де також показані рейтинги половини зірок.

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

Ви називаєте метод із таким порядком малюнків:

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

ПРИМІТКА. Також потрібно вказати атрибути "max" та "numStars" у XML, інакше половина зірок не відображається.


єдиний спосіб, який працює для мене на API19, але я не відмовився шукати спосіб зробити це лише з xml T_T
Beeing Jk

@BeeingJk, якщо ви створили спеціальний вид, що розширює RatingBar, ви можете створити власні атрибути xml, щоб вказати колір відтінку. Потім у вас є одна точка контролю за налаштуванням відтінку і ви можете вказати відтінок у xml. Сподіваюся, що це допомагає! Можна пояснити більше, якщо потрібно
Форест Біс

Mode.SRC_INабо Mode.MULTIPLY?
Dr.jacky

12

Тепер ви можете використовувати DravableCompat від AppCompat v22.1.0 і далі, щоб динамічно підфарбовувати всі види малюнків, що корисно, коли ви підтримуєте кілька тем з одним набором малюнків. Наприклад:

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

Це назад сумісно з API 4. Також дивіться допис у блозі Кріса Бейнса на тему « Підтримка бібліотек» v22.1.0

Для фактичного розміру та форми вам потрібно буде визначити новий стиль малюнка та малювання списків шарів відповідного розміру, як інші вже відповіли вище.


Малюнки - це не масиви, як ви отримуєте доступ до прогресу [0]?
blueice

@blueice Ви маєте рацію, Dravable має бути LayerDrawable, виправлена ​​зараз, дякую.
Dan Dar3

Ще не здавалося, що для мене це працює, я закінчив те, що Юрій Виноградов поставив іншу відповідь на це питання, і це, здається, працює.
blueice

Як змінити Dravable замість Змінити колір?
Іман Мараші

@ImanMarashi Дивіться відповідь Алекса на основі XML вище, LayerDravable.setDrawable (індекс, черпаючий) доступний лише з API23.
Ден Dar3

10

Використовувати android:themeатрибут:

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" />

9

Для просто зміни кольору рядка рейтингу від xml: -

android:progressTint="@color/your_color"
android:backgroundTint="@color/your_color"
android:secondaryProgressTint="@color/your_color"

він не змінює порожній колір зірки
Nainal

7

Щоб змінити колір, вам просто потрібно встановити параметр 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"
       />

За розміром властивість стилю.


працює лише на API 21 або вище, дякую
Джунаїд

5

Найпростіший спосіб:

android:progressTint="@color/color"

1
Зауважте, що це працює лише на api
21+

4

Відповідь Building @ lgvalle.

Оновлення 2015 року

Тепер ви можете використовувати DravableCompat для тонування всіх видів малюнків. Наприклад:

Dravable progress = ratingBar.getProgressDravable (); DravableCompat.setTint (прогрес, колір.WHITE); Це назад сумісний з 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));

Це збереже кольори кроків дробу.


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

використовувати свій власний колір


4

Без додавання нового стилю ви можете використовувати колір відтінку в межах 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

Працює для Android нижче та вище версії 21

Після деяких досліджень я придумав цей метод встановити фоновий відтінок, відтінок розриву (напр .: напівзірка) та колір відтінку зірки.

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

3

Просте рішення, використовуйте AppCompatRatingBar та його метод setProgressTintList, щоб досягти цього, див. Цю відповідь для ознайомлення.


Це працювало для мене під API 28, використовуючи com.google.android.material: material: 1.1.0-alpha02
Mark Lapasa

2

Я вирішую це питання наступним чином:

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

Дякую, це працює. Але для дробового рейтингу зірки малюються цілком.
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);

для мене це працює ....


1

Я знайшов просте рішення щодо зміни кольору зірки відповідно до вашої теми.

Перейти на цей сайт: http://android-holo-colors.com/

Виберіть колір теми та створіть зірочки.


1

Використовуючи відповіді вище, я створив швидкий статичний метод, який можна легко використати повторно. Він спрямований лише на тонування кольору прогресу для активованих зірок. Зірки, які не активовані, залишаються сірими.

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

Просто передайте свою рейтингову смужку та колір getResources().getColor(R.color.my_rating_color)

Як бачите, я використовую DravableCompat, щоб він був сумісним назад.

EDIT: Цей метод не працює на API21 (зрозуміти чому). У кінцевому підсумку ви отримуєте NullPointerException при виклику setProgressBar. Я відключив весь метод в API> = 21.

Для API> = 21 я використовую рішення SupperPuccio.


java.lang.ClassCastException: android.support.v4.graphics.dravable.DravableWrapperHoneycomb не можна передавати на android.graphics.dravable.LayerDravable on pre-lollipop
Ishaan Garg

1
@IshaanGarg ви праві. Я зіткнувся з тим же питанням і оновив свій метод. Я оновив свій код для розгляду справи. Я не думаю, що це питання Android версії. Якщо ви використовуєте меншу версію рейтингової панелі (з style = "? Android: attr / ratingBarStyleSmall"), то повернений файл, що повертається, все ще є LayoutDravable.
JDenais

Так, саме те, що я реалізував, просто не забудьте скористатися AppCompatRatingBar. Хоча я не в змозі отримати півзірки при попередньому встановленні рейтингу з XML / java. Як і setRating (3.5) показує 4 повних зірки
Ішаан Гарг

1

Рядок оцінки використовується автоматично під час виконання для зміни кольору на сенсорній зірці.

Спочатку додайте стиль у файл 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>

Тоді у вашій рейтинговій смузі додається така тема:

<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"/>

0

1) оголосити цей 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) у 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) рейтинг активний --- візьміть будь-яке зображення з темним кольором, оскільки воно буде використовуватися як прозорість кольорів для різних рейтингів

rating_inactive - візьміть будь-яке зображення такого ж розміру, як зазначено вище, зі світлим фоном. Він буде використовуватися, коли не вибрано рейтинг


0

Дуже простий спосіб зміни кольору кордону зірок - це використання параметра xml:

android:progressBackgroundTint=""

у вікні рейтингуБар. Значення має бути шістнадцятковим кодом для кольору.


Я не знаю чому, але здається, що ви впливаєте лише на межу зірок (колір заповнення залишається кольором за замовчуванням)
superpuccio

Гаразд, ви пропустили кілька xml парамів. Перевірте мою відповідь нижче.
superpuccio

1
Ти маєш рацію. Я не знаю, чому я думав, що у нього виникли проблеми зі зміною кольору кордону зірки (можливо тому, що якщо у мене проблема). Ваша відповідь більш повна.
Пау Арландіс Мартінес

0

Я шукав надійний метод зробити це аж до API 9 принаймні. Рішення "кастинг на LayerDrawble" здавалося для мене ризикованим рішенням, і коли я тестував його на телефоні Android на 2.3, він успішно передавався, але дзвінок на DravableCompat.setTint (...) не мав жодного ефекту.

Не здавалося, що для мене теж не вдалося вирішити необхідність завантаження ресурсів.

Я вирішив зашифрувати власне рішення - клас, що розширює додаток AppCompatRatingBar, використовуючи користувацький Dravable, що піклується про те, щоб малювати зірки програмно. Він ідеально підходить для моїх потреб, я опублікую його на випадок, якщо хтось допоможе:

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

Посилання легше, оскільки ви можете отримати повний файл безпосередньо, але ось повний код на всякий випадок:

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

0

Трохи пізня відповідь, але я сподіваюся, що це допоможе деяким людям.

<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" />

І ось як виглядає WhiteRatingStar

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

З цим зірки будуть, наприклад, пофарбовані в білий колір.



-1

Як випливає з попередньої відповіді, змінити колір рейтингової панелі непросто. Зорі програмно не намальовані, це зображення з фіксованим розміром та певними градієнтами кольорів. Щоб змінити колір, вам потрібно створити власні зображення зірок з різними кольорами, після чого перейдіть до створення власного ресурсу XML, що виводиться, та передайте його до класу ratingsBar, використовуючи setProgressDravable (Dravable d) або атрибут XML android: progressDravable.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.