Como posso alterar as cores e o tamanho das estrelas?
Como posso alterar as cores e o tamanho das estrelas?
Respostas:
Etapa 1: Crie seu próprio estilo, clonando um dos estilos existentes (de $ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml
), colocando-o no seu próprio projeto styles.xml
e fazendo referência a ele quando você adiciona o widget a um layout.
Etapa 2: crie seus próprios LayerDrawable
recursos XML para o RatingBar
, apontando para as imagens apropriadas a serem usadas na barra. Os estilos originais apontarão para os recursos existentes com os quais você pode comparar. Em seguida, ajuste seu estilo para usar seus próprios LayerDrawable
recursos, em vez dos recursos internos.
É um pouco complicado no blog mencionado, usei uma maneira semelhante, mas mais simples. Você precisa de imagens de 3 estrelas (red_star_full.png, red_star_half.png e red_star_empty.png) e um xml, só isso.
Coloque essas 3 imagens em res / drawable.
Coloque aqui a seguinte 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>
e, finalmente, diga à sua definição da barra de classificação para usar isso, ou seja,
<RatingBar android:progressDrawable="@drawable/ratingbar_red"/>
É isso aí.
Tente isso, se você quiser apenas mudar de cor:
RatingBar ratingBar = (RatingBar) findViewById(R.id.ratingBar);
LayerDrawable stars = (LayerDrawable) ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
PorterDuff.Mode.SRC_ATOP
significa ou faz?
Drawable stars = rb.getProgressDrawable(); stars.setTint( Color.YELLOW );
A maneira mais fácil que funcionou para mim ... se você estiver estendendo a Atividade AppCompat
Em seu build.gradle, adicione a biblioteca appcompat mais recente.
dependencies {
compile 'com.android.support:appcompat-v7:X.X.X' // where X.X.X version
}
Faça sua atividade estender android.support.v7.app.AppCompatActivity
public class MainActivity extends AppCompatActivity {
...
}
Declare o estilo customizado em seu arquivo styles.xml.
<style name="RatingBar" parent="Theme.AppCompat">
<item name="colorControlNormal">@color/indigo</item>
<item name="colorControlActivated">@color/pink</item>
</style>
Aplique esse estilo à sua RatingBar via atributo 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"/>
style="?android:ratingBarStyleSmall"
juntos.
<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>
e sua classificaçãoBar android:theme="@style/RatingBarSmallTheme"
Atualização de 2015
Agora você pode usar DrawableCompat para colorir todos os tipos de drawables. Por exemplo:
Drawable progress = ratingBar.getProgressDrawable();
DrawableCompat.setTint(progress, Color.WHITE);
Isso é compatível com versões anteriores até API 4
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}
uma vez que está trabalhando por padrão de API 22.
A partir da API 21 , é muito fácil alterar a cor das estrelas com estas três linhas de código:
android:progressTint="@android:color/holo_red_dark"
android:progressBackgroundTint="@android:color/holo_red_dark"
android:secondaryProgressTint="@android:color/holo_red_dark"
Fazendo assim, você mudará:
Se você deseja alterar a cor de todas as estrelas, declarei o meu 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);
As soluções que Alex e CommonsWares publicaram estão corretas. Uma coisa sobre a qual o Android nunca fala é sobre tamanhos de pixels adequados para diferentes densidades. Aqui estão as dimensões necessárias para cada densidade com base na luz halo.
Estrela pequena
mdpi: 16px
hdpi: 24px
xhdpi: 32px
xxhdpi: 48px
Estrela Média
mdpi: 24px
hdpi: 36px
xhdpi: 48px
xxhdpi: 72px
Estrela grande
mdpi: 35px
hdpi: 52px
xhdpi: 69px
xxhdpi: 105px
Então, eu estou lutando com esse problema há duas horas e criei uma solução funcional para todas as versões da API, onde também são mostradas classificações de meia estrela.
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);
}
}
Você chama o método com esta ordem de drawables:
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: Você também deve especificar os atributos "max" e "numStars" em XML, caso contrário, meias estrelas não serão exibidas.
Mode.SRC_IN
ou Mode.MULTIPLY
?
Agora você pode usar o DrawableCompat a partir do AppCompat v22.1.0 para colorir dinamicamente todos os tipos de drawables, úteis quando você oferece suporte a vários temas com um único conjunto de drawables. Por exemplo:
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
Isso é compatível com a API 4. Consulte também a publicação no blog de Chris Banes em Support Libraries v22.1.0
Para o tamanho e a forma reais, você precisará definir um novo estilo e drawables de lista de camadas para o tamanho apropriado, como outros já responderam acima.
Usar 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" />
Para mudar a cor basta colocar o 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 o tamanho da propriedade style.
Construindo a resposta da @ lgvalle.
Atualização de 2015
Agora você pode usar DrawableCompat para colorir todos os tipos de drawables. Por exemplo:
Progresso desenhável = ratingBar.getProgressDrawable (); DrawableCompat.setTint (progress, Color.WHITE); Isso é compatível com versões anteriores até 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));
Isso manterá as cores das etapas da fração.
Sem adicionar um novo estilo, você pode usar a cor da tonalidade dentro do 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"/>
Depois de algumas pesquisas, desenvolvi esse método para definir a tonalidade de fundo, a diferença de espaço (ex: meia estrela) e a cor da tonalidade da estrela.
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
Solução simples, use AppCompatRatingBar e seu método setProgressTintList para conseguir isso; consulte esta resposta para referência.
Eu resolvo esse problema da seguinte maneira:
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);
Encontrei uma solução simples para mudar a cor da estrela de acordo com o seu tema.
Ir para este site: http://android-holo-colors.com/
Escolha a cor do seu tema e crie suas imagens de estrelas.
Usando as respostas acima, criei um método estático rápido que pode ser facilmente reutilizado. Ele visa apenas colorir a cor do progresso das estrelas ativadas. As estrelas que não são ativadas permanecem cinza.
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;
}
}
Basta passar sua barra de classificação e uma cor usando getResources().getColor(R.color.my_rating_color)
Como você pode ver, eu uso o DrawableCompat, por isso é compatível com versões anteriores.
EDIT: Este método não funciona na API21 (veja o porquê). Você acaba com um NullPointerException ao chamar setProgressBar. Acabei desativando todo o método na API> = 21.
Para API> = 21, eu uso a solução SupperPuccio.
A barra de classificação é usada automaticamente no tempo de execução para alterar a cor na estrela de toque.
Primeiro adicione estilo no arquivo 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>
Em seguida, sua barra de classificação adiciona um 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"/>
1) declarar 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) em 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) classificação ativa --- tire qualquer imagem com cor escura, pois ela será usada como transparência de cores para classificações diferentes
rating_inactive - tira qualquer imagem do mesmo tamanho da imagem acima com fundo claro ... será usada quando nenhuma classificação for selecionada
Uma maneira muito fácil de alterar a cor da borda das estrelas é usar o parâmetro xml:
android:progressBackgroundTint=""
na visualização ratingBar. O valor deve ser um código hexadecimal para uma cor.
Eu estava procurando por um método confiável para fazer isso até a API 9, pelo menos. A solução "transmitir para LayerDrawble" parecia uma solução arriscada para mim e, quando o testei em um telefone Android no 2.3, foi transmitida com sucesso, mas a chamada para DrawableCompat.setTint (...) não teve nenhum efeito.
A necessidade de carregar recursos extraíveis também não me pareceu uma boa solução.
Decidi codificar minha própria solução, que é uma classe que estende AppCompatRatingBar, usando um Drawable personalizado, cuidando de desenhar as estrelas programaticamente. Funciona perfeitamente para as minhas necessidades, postarei caso ajude alguém:
https://gist.github.com/androidseb/2b8044c90a07c7a52b4bbff3453c8460
O link é mais fácil porque você pode obter o arquivo completo diretamente, mas aqui está o código completo, apenas no caso de:
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;
}
}
}
Resposta um pouco tarde, mas espero que ajude algumas pessoas.
<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" />
E aqui está a aparência do WhiteRatingStar
<style name="WhiteRatingStar" parent="Base.Widget.AppCompat.RatingBar.Small">
<item name="colorAccent">@android:color/white</item>
</style>
Com isso, as estrelas serão coloridas em branco, por exemplo.
Como a resposta anterior indica, não é fácil alterar a cor da barra de classificação. As estrelas não são desenhadas programaticamente, são imagens com tamanho fixo e gradientes de cores específicos. Para alterar a cor, você deve criar suas próprias imagens de estrela com cores diferentes e, em seguida, criar seu próprio recurso XML desenhável e passá-lo para a classe ratingsBar usando o atributo setProgressDrawable (Drawable d) ou XML android: progressDrawable.