Android RatingBar изменит цвета звездочек [закрыто]

142

Как я могу изменить цвет и размер звездочек?

d-man
источник
Я думаю, вам нужно создать свою собственную панель рейтинга, если вы хотите это сделать,
Донал Рафферти,
Я написал сообщение в блоге, описывающее, как изменить изображения RatingBar: kozyr.zydako.net/2010/05/23/pretty-ratingbar Он также показывает, где вы можете указать размер изображения ...
kozyr 06
Я надеялся, что этот вопрос касается разноцветной шкалы оценок, показанной на веб-сайтах, но не смог найти себе ни одной. Простую реализацию создал сам github.com/codebreaker/coloredbar-android . Надеюсь, это поможет кому-то там.
jaga

Ответы:

26

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

Шаг № 2: Создайте свои собственные LayerDrawableXML-ресурсы для RatingBarпанели, указав соответствующие изображения. Исходные стили укажут вам на существующие ресурсы, с которыми вы можете сравнить. Затем настройте свой стиль, чтобы использовать собственные LayerDrawableресурсы, а не встроенные.

CommonsWare
источник
1
Согласно шагу № 2, это не работает для устройств Samsung 3 или некоторых других, это не обязательно, чтобы быть LayerDrawable. См. Информацию здесь: stackoverflow.com/questions/30266334/…
Кенни
6
Используйте android: progressTint = "@ color / yellow". См. Ответ @superpuccio.
Винсент
2
progressTint поддерживается только выше 21 уровня api
Йогеш Рати
Это лучшее решение: stackoverflow.com/a/36297738/1935135
Андре Луис Рейс
121

В упомянутом блоге это немного сложно, я использовал аналогичный, но более простой способ. Вам нужны изображения с тремя звездами (red_star_full.png, red_star_half.png и red_star_empty.png) и один xml, вот и все.

Поместите эти 3 изображения в res / drawable.

Поместите туда следующий файл 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>

и, наконец, скажите вашему определению панели рейтинга использовать это, т.е.

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

Вот и все.

Alex
источник
3
Привет, Алекс, я пробовал это решение, но когда я пытаюсь установить рейтинг примерно на 1,1, 1,2 и т. Д., Он отображается как 1,5. Я сделал 3-звездочные изображения: одно пустое, одно наполовину полное и одно полное. Я предполагаю, что он должен интерполировать между ними, чтобы получить дробные компоненты, мне просто интересно, была ли у кого-нибудь такая же проблема, или я делаю что-то заметно не так?
Грэм Байтсон
Не могли бы вы рассказать мне об изображениях, которые мы должны использовать, если это цветные изображения и размер изображений, которые я не могу решить ...
Притхвирадж Широор
1
Все видят ответ на обновление 2015 года ниже! Все намного проще и проще!
Кэти
Этот ответ по-прежнему обеспечивает большую гибкость в отношении различных состояний звезд.
Том Бевеландер
Почему под звездами появляются вертикальные линии? Я попытался определить собственный стиль, указав высоту, но на моем AVD все еще есть вертикальные линии под звездами.
Aleksandar
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
@zyamys Это действительно отстой = (Необходим метод для «более высоких версий» и другой метод для более старых версий?
Даниэла Мораис
1
Он работает только с точностью 0,5. В противном случае (точность <0,5) наложение становится странным и кажется, что синий цвет все еще имеет точность 0,5, а желтый - точный
Тео Инке
1
Предупреждение: сбои на устройствах pre-lolipop. Примите принятый ответ.
blockwala
70

Самый простой способ, который сработал для меня ... если вы расширяете AppCompat Activity

В свой build.gradle добавьте последнюю библиотеку appcompat.

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: theme.

<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, и да, он работает.
Prashant
Это лучшее решение.
Архат
Это должен быть выбранный правильный ответ.
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"
Захар Родионов
46

Обновление 2015 г.

Теперь вы можете использовать DrawableCompat для тонирования всех видов чертежей. Например:

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

Это обратно совместимо до API 4

lgvalle
источник
Не забудьте вернуть возможность рисования на рейтинговой панели.
дожим
16
Это окрашивает всю фигуру в один цвет, что затрудняет различение пустых звезд.
blueice
Это работает только с библиотекой поддержки Android> = 22, но не с библиотекой поддержки <22.
Raghav Sharma
3
Он рисует 5 цветных звезд, а не 3,5.
CoolMind,
1
Я бы просто окружил это, if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}поскольку он работает по умолчанию из API 22.
Йоанн Эркуэ,
40

Начиная с 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)
  • и цвет границы (secondaryProgressTint) звезд
суперпуччо
источник
Вместо 3,5 красит 4 звезды.
CoolMind
@CoolMind установил android: stepSize: 1 вместо 0.5
eLemEnt
4
Как изменить цвет пустой звезды?
winklerrr
@winklerrr вы нашли решение, как изменить цвет пустой звезды.
Tarun Kumar
Не проводил дополнительных проверок, чтобы найти решение
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 (context, 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
Dirkoneill
источник
могу ли я использовать vectordrawble со звездами
Мина Фаузи,
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?
Доктор Джеки
12

Теперь вы можете использовать DrawableCompat из 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.

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

Дэн Дар3
источник
Чертежи - это не массивы. Как вы получаете доступ к прогрессу [0]?
blueice
@blueice Вы правы, извините, Drawable должен быть LayerDrawable, теперь исправлено, спасибо.
Дэн Дар3
У меня все еще не получалось, я получил то, что Юрий Виноградов дал другой ответ на этот вопрос, и это, похоже, сработало.
blueice
Как изменить Drawable вместо Change Color?
Иман Мараши
@ImanMarashi См. Ответ Алекса на основе XML выше, LayerDrawable.setDrawable (index, drawable) доступен только начиная с API23.
Dan 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"
Рахул
источник
он не меняет цвет пустой звезды
Наинал
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"
       />

Для размера свойство стиля.

Letrounet
источник
работает только с API 21 или выше, спасибо
Junaid
5

Без добавления нового стиля вы можете использовать цвет оттенка в 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
источник
5

Самый простой способ:

android:progressTint="@color/color"
Мехатаб
источник
1
Обратите внимание, что это работает только на api 21+
Ixx 05
4

Строим ответ @lgvalle.

Обновление 2015 г.

Теперь вы можете использовать DrawableCompat для тонирования всех видов чертежей. Например:

Возможный прогресс = ratingBar.getProgressDrawable (); DrawableCompat.setTint (прогресс, Color.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));

Это сохранит цвета ступеней дроби.

Splangi
источник
4
<!--For rating bar -->
    <style name="RatingBarfeed" parent="Theme.AppCompat">
        <item name="colorControlNormal">@color/colorPrimary</item>
        <item name="colorControlActivated">@color/colorPrimary</item>
    </style>

используйте свой собственный цвет

Сибасиш
источник
4

Работает для 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
Марк Лапаса
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/

Выберите цвет темы и создайте свои звездные изображения.

Hardik4560
источник
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)

Как видите, я использую DrawableCompat, поэтому он обратно совместим.

РЕДАКТИРОВАТЬ: этот метод не работает на API21 (поймите, почему). Вы получаете исключение NullPointerException при вызове setProgressBar. В итоге я отключил весь метод на API> = 21.

Для API> = 21 я использую решение SupperPuccio.

JDenais
источник
java.lang.ClassCastException: android.support.v4.graphics.drawable.DrawableWrapperHoneycomb не может быть
преобразован
1
@IshaanGarg, ты прав. Я столкнулся с той же проблемой и обновил свой метод. Я обновил свой код, чтобы справиться с этим случаем. Не думаю, что дело в версии андроида. Если вы используете уменьшенную версию панели рейтинга (с style = "? Android: attr / ratingBarStyleSmall"), то возвращаемый объект для рисования по-прежнему будет LayoutDrawable.
JDenais
Да, именно то, что я реализовал, просто обязательно используйте AppCompatRatingBar. Хотя я не могу получить половину звезды при предварительной установке рейтинга из XML / java. Like setRating (3.5) показывает 4 полных звезды
Ишаан Гарг 01
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=""

в режиме просмотра ratingBar. Значение должно быть шестнадцатеричным кодом цвета.

Пау Арландис Мартинес
источник
Не знаю почему, но похоже, что ваш метод влияет только на границу звезд (цвет заливки остается цветом по умолчанию)
superpuccio
Хорошо, вы пропустили некоторые параметры xml. Посмотрите мой ответ здесь ниже.
superpuccio
1
Ты прав. Я не знаю, почему я подумал, что у него проблемы с изменением цвета границы звезды (может быть, потому что проблема была у меня). Ваш ответ более полный.
Пау Арландис Мартинес 01
0

Я искал надежный способ сделать это, по крайней мере, до API 9. Решение «преобразование в LayerDrawble» показалось мне рискованным решением, и когда я протестировал его на телефоне Android на 2.3, оно было выполнено успешно, но вызов DrawableCompat.setTint (...) не дал никакого эффекта.

Необходимость загрузки выводимых ресурсов мне тоже не показалась хорошим решением.

Я решил написать собственное решение, которое представляет собой класс, расширяющий AppCompatRatingBar, с использованием настраиваемого Drawable, заботящегося о программном рисовании звезд. Он отлично работает для моих нужд, выложу на случай, если кому-то поможет:

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;
        }
    }
}
androidseb
источник
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 с возможностью рисования и передать его классу ratingBar с помощью setProgressDrawable (Drawable d) или атрибута XML android: progressDrawable.

Дэвид
источник