Android RatingBar更改星形颜色[关闭]


141

如何更改星星的颜色和大小?


我认为你必须创建自己的定制等级吧,如果你想这样做
多纳尔拉弗蒂

我写了一篇博客文章,描述了如何更改RatingBar图像:kozyr.zydako.net/2010/05/23/pretty-ratingbar它还显示了您可以在其中指定图像大小的地方...
kozyr 2010年

我希望这个问题是针对网站上显示的彩色评分栏,我自己找不到。我自己创建了一个简单的实现github.com/codebreaker/coloredratingbar-android。希望这可以帮助某人。
13年

Answers:


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级别以上受支持
Yogesh Rathi


120

在提到的博客中这有点复杂,我使用了类似但简单的方法。您只需要3星图像(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"/>

而已。


3
嗨,Alex,我已经尝试过这种解决方案,但是当我尝试将等级设置为1.1、1.2等时,它显示为1.5。我拍了3张星图,一张是空的,一张是半满的,一张是满的。我想应该在它们之间进行插值以获得小数部分,我只是想知道是否还有其他人遇到相同的问题,或者我做错了什么?
Graham Baitson 2014年

您能告诉我有关图像的电话吗,我们应该使用它的彩色图像和无法解决此问题的图像大小...
Prithviraj Shiroor 2015年

1
每个人都在下面看到2015年更新答案!更容易,更简单!
katie 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 2015年

@zyamys这真的很烂=(“更高版本的方法”和旧版本的方法是否必要?
Daniela Morais 2015年

1
它仅适用于0.5的精度。否则(精度<0.5),覆盖层会变得怪异,看起来蓝色仍然精度为0.5,而黄色精度为
Teo Inke,2015年

1
警告:脂质前设备崩溃。接受接受的答案。
blockwala 2015年

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>  

通过android:theme属性将此样式应用于您的RatingBar。

<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)和棉花糖6.0.1(Samsung Galaxy On Nxt)上试用了它,它起作用了。但是在Lollipop 5.1(Micromax)上没有成功。对于棒棒糖,我在RatingBar中使用了“ android:progressTint”属性,是的,它可以工作。
Prashant

那是最好的解决方案。
阿罗汉·拜德

这应该是选择的正确答案。
HampelElőd17年

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> 和您的评分Bar android:theme="@style/RatingBarSmallTheme"
Zakhar Rodionov

47

2015年更新

现在,您可以使用DrawableCompat着色所有类型的可绘制对象。例如:

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

向下兼容API 4


别忘了将可绘制对象重新设置在ratingBar上。
挤压

15
这会将整个可绘制对象着色为一种颜色,这使得空星星很难分辨。
blueice

这仅适用于android支持库> = 22,不适用于支持库<22。
Raghav Sharma 2015年

2
它绘制5个彩色星星,而不是3.5个。
CoolMind

1
我只想环绕,与if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {}因为它在默认情况下,从API 22.工作
约恩·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)
  • 和星星的边框颜色(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现在已被弃用,还有其他选择吗?
Manohar Reddy

2
您可以在此处找到答案stackoverflow.com/a/32202256/2513291例如,这种方法ContextCompat.getColor(context,R.color.color_name)
Yuriy Vinogradov

效果很好,但是请注意,由于某种原因,顺序很重要(2,然后是1,然后是0)。我尝试了相反的操作,并在第一次更改颜色时导致了一些UI故障。
西蒙·尼农

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

我可以将vectordrawble与星星一起使用吗
Mina Fawzy

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

注意:此外,您还必须在XML中指定属性“ max”和“ numStars”,否则不会显示半星。


在API19上对我有效的唯一方法,但我没有放弃寻找仅从xml来执行此操作的方法T_T
Beeing Jk

@BeeingJk如果您创建扩展RatingBar的自定义视图,则可以创建自己的xml属性以指定色调颜色。这样,您就可以设置色彩的单一控制点,并且可以在xml中指定色彩。希望有帮助!如果需要的话,可以解释更多
Forrest Bice

Mode.SRC_IN还是Mode.MULTIPLY
Dr.jacky '18

12

现在,您可以使用AppCompat v22.1.0及更高版本中的DrawableCompat来动态着色所有类型的可绘制对象,当您通过一组可绘制对象支持多个主题时,此功能非常有用。例如:

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

它向下兼容API4。另请参阅Chris Banes在Support Libraries v22.1.0上的博客文章。

对于实际的尺寸和形状,您将需要定义新的样式和适用于相应尺寸的图层列表可绘制对象,就像上面其他人已经回答的那样。


可绘制对象不是数组如何访问progress [0]?
blueice

@blueice对不起,Drawable应该是LayerDrawable,现在已更正,谢谢。
Dan Dar3 2015年

似乎对我来说仍然行不通,最后我得到了尤里·维诺格拉多夫(Yuriy Vinogradov)对这个问题的不同回应,这似乎行得通。
blueice

如何更改Drawable而不是更改颜色?
伊曼·马拉希

@ImanMarashi请参见上面的Alex基于XML的答案,LayerDrawable.setDrawable(index,drawable)仅可从API23开始使用。
Dan Dar3'3

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或更高版本,谢谢
Junaid

5

最简单的方法:

android:progressTint="@color/color"

1
请注意,这仅适用于api 21+
Ixx

4

建立@lgvalle的答案。

2015年更新

现在,您可以使用DrawableCompat着色所有类型的可绘制对象。例如:

可绘制进度= ratingBar.getProgressDrawable(); DrawableCompat.setTint(progress,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));

这将保留分数步长颜色。


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

适用于版本21以上的Android

经过研究后,我想出了这种方法来设置背景色,间隙色(例如:半星)和星色。

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


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

使用上面的答案,我创建了一个可以轻松重用的快速静态方法。它仅旨在为激活的星星着色进度色。未激活的星星保持灰色。

    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上不起作用(请弄清楚为什么)。调用setProgressBar时,您最终遇到NullPointerException。我最终在API> = 21上禁用了整个方法。

对于API> = 21,我使用SupperPuccio解决方案。


java.lang.ClassCastException:android.support.v4.graphics.drawable.DrawableWrapperHoneycomb无法转换为android.graphics.drawable.LayerDrawable在棒棒糖之前
Ishaan Garg,2015年

1
@IshaanGarg你是对的。我遇到了同样的问题,并更新了我的方法。我更新了代码以处理此案。我认为这不是Android版本的问题。如果您使用评分栏的较小版本(带有style =“?android:attr / ratingBarStyleSmall”),则返回的drawable仍然是LayoutDrawable。
JDenais

是的,只是我已经实现的,请确保使用AppCompatRatingBar。尽管从XML / java预先设置等级时我无法获得半颗星。就像setRating(3.5)一样,它显示了4个完整的星星
Ishaan Garg

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
你是对的。我不知道为什么我在想他在更改星星的边框颜色时遇到问题(也许是因为我遇到的问题)。您的答案更加完整。
波城阿兰迪斯·马丁内斯

0

我一直在寻找一种可靠的方法,至少可以一直执行到API 9。对我来说,“广播到LayerDrawble”解决方案似乎是一个冒险的解决方案,当我在2.3的Android手机上对其进行测试时,它成功投射,但对DrawableCompat.setTint(...)的调用没有任何效果。

对我来说,加载可绘制资产的需求似乎也不是一个好的解决方案。

我决定使用一个自定义Drawable编写我自己的解决方案,该解决方案是扩展AppCompatRatingBar的类,并负责以编程方式绘制星星。它非常适合我的需求,如果有帮助,我会予以张贴:

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

正如前面的答案所暗示的那样,更改等级栏的颜色并不容易。这些星星不是通过程序绘制的,它们是具有固定大小和特定颜色渐变的图像。要更改颜色,您必须创建自己的具有不同颜色的星形图像,然后继续创建自己的drawable XML资源,并使用setProgressDrawable(Drawable d)或XML属性android:progressDrawable将其传递给ratingBar类。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.