Android评分条如何更改星星颜色

148

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


如果你想要这样做,我认为你必须创建自己的定制评分栏。 - Donal Rafferty
我写了一篇博客文章,描述了如何更改RatingBar图像:http://kozyr.zydako.net/2010/05/23/pretty-ratingbar/ 它还展示了您可以指定图像大小的位置... - kozyr
我希望这个问题是关于多彩评分栏的,就像网站上展示的那样,但我自己找不到一个。于是我自己创建了一个简单的实现 https://github.com/codebreaker/coloredratingbar-android 。希望这能帮助到某些人。 - jaga
31个回答

122

在所提到的博客中,有点复杂,我使用了一种类似但更简单的方法。 你需要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 定义使用它,即:

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

就是这样。


3
嗨,Alex,我尝试了这个解决方案,但是当我尝试将评分设置为1.1、1.2等时,它会显示为1.5。我已经准备好了三张星级图片,一张空的,一张半满的和一张满的。我认为它应该在它们之间进行插值以获得小数部分,我只是想知道是否有其他人遇到过同样的问题,或者我做错了什么明显的事情? - Graham Baitson
请问一下我们应该使用什么样的图片,是彩色图片还是黑白图片?另外图片的尺寸是多少呢?我无法解决这个问题,请帮忙解答一下。 - Prithviraj Shiroor
1
大家看到下面的2015年更新答案了吗!它更容易和简单! - katie
这个答案仍然在星星的不同状态下提供了更多的灵活性。 - Tom Bevelander
为什么我的AVD下面的星星下面会出现垂直线?我尝试定义自定义样式,指定高度,但星星下面仍然有垂直线。 - Aleksandar
我可以让每个星星都有不同的颜色,比如第一个星星是红色,第二个星星是蓝色,第三个星星是黄色,最后一个星星是绿色,这种情况是否可行? - Darshan Khatri

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及以上版本。需要使用以下代码:stars.setTint(Color.YELLOW);``` - zyamys
1
它只适用于0.5的精度。否则(精度<0.5),叠加会变得奇怪,似乎蓝色仍然是0.5的精度,而黄色是精确的。 - Teo Inke
1
警告:在早期的Lolipop设备上会崩溃。请采用被接受的答案。 - Karan
在Galaxy Nexus 4.2.1 Jelly Bean上运行良好。 - Richard Le Mesurier
显示剩余4条评论

74

我觉得最容易的方法是...如果你要扩展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(三星S3 neo)和Marshmallow 6.0.1(三星Galaxy On Nxt)上尝试了它,成功了。但是在Lollipop 5.1(Micromax)上没有成功。对于Lollipop,我在RatingBar中使用了“android:progressTint”属性,是的,它可以工作。 - Prashant
那是最好的解决方案。 - Arhat Baid
这应该是所选的正确答案。 - Hampel Előd
1
这是最佳解决方案。如果您想更改星级大小,可以一起使用 style="?android:ratingBarStyleSmall" - André Luiz Reis
@AndréLuizReis <style name="RatingBarSmallTheme" parent="Theme.AppCompat"> <item name="colorControlNormal">@color/colorOrangeNormal</item> <item name="colorControlActivated">@color/colorOrangeActivated</item> <item name="ratingBarStyle">@style/Widget.AppCompat.RatingBar.Small</item> </style>以及你的评分条android:theme="@style/RatingBarSmallTheme" - Zakhar Rodionov

52

从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
6
如何更改空心星形的颜色? - winklerrr
@winklerrr,你找到如何更改空星的颜色的解决方案了吗? - Tarun Kumar
没有进行进一步的检查以找到解决方案。 - winklerrr

47

2015年更新

现在你可以使用DrawableCompat来给各种drawable上色。例如:

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

这是向后兼容的,支持 API 4 及更早版本。


16
这会将整个可绘制对象渲染成一种颜色,这使得空星很难被区分出来。 - blueice
这仅适用于Android支持库>=22,而不适用于支持库<22。 - Raghav Sharma
@Terence,这不是必要的。 - ElYeante
3
它会绘制5个彩色的星星,而不是3.5个。 - CoolMind
1
我会将其包裹在 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {} 中,因为它默认从API 22开始工作。 - Yoann Hercouet
显示剩余4条评论

37

如果你想改变所有星形状态的颜色,可以使用以下方法:

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。那么我只需要更改前4颗星星,而不是全部更改。 - user2424370
1
getColor现在已经被弃用了,有什么替代方案吗? - Manohar
2
你可以在这里找到答案 https://dev59.com/LFwZ5IYBdhLWcg3wG9F_#32202256,例如使用这种方法 ContextCompat.getColor(context, R.color.color_name)。 - Yuriy Vinogradov
运行良好,但请注意,由于某种原因,顺序很重要(2,然后1,然后0)。我尝试了反向操作,但在第一次更改颜色时导致了一些UI故障。 - Simon Ninon

27

步骤#1:创建自己的样式,通过克隆现有样式(从$ANDROID_HOME/platforms/$SDK/data/res/values/styles.xml)并将其放在自己项目的styles.xml中,在将小部件添加到布局时引用它。

步骤#2:为RatingBar创建自己的LayerDrawable XML资源,指向适合用于该栏的图片。原始样式将指向您可以与之比较的现有资源。然后,调整您的样式以使用您自己的LayerDrawable资源,而不是内置资源。


1
根据步骤#2,此方法不适用于三星3设备或某些其他设备,而且这也不需要是一个LayerDrawable。请参阅此处的信息:https://dev59.com/L4rda4cB1Zd3GeqPSeia - Kenny
6
请使用android:progressTint="@color/yellow"。请参考@superpuccio的回答。 - Vincent
2
progressTint 只支持 21 及以上的 API 级别。 - Yogesh Rathi
这是最佳解决方案:https://dev59.com/tnE95IYBdhLWcg3wHqSl#36297738 - André Luiz Reis

25

所以我已经为这个问题苦苦挣扎了两个小时,最终想出了一个适用于所有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

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

我能否使用VectorDrawable与星形图案? - Mina Fawzy

13

现在,从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

这是向后兼容的,可以向下兼容到API 4。此外,请参阅Chris Banes关于Support Libraries v22.1.0的博客文章。

对于实际的大小和形状,您需要为适当的大小定义一个新的样式和层列表可绘制对象,就像其他人已经在上面回答的那样。


Drawables不是数组,你是如何访问progress[0]的? - blueice
@blueice 你是对的,抱歉,Drawable 应该是 LayerDrawable,已经更正了,谢谢。 - Dan Dar3
似乎对我仍然没有起作用,最终我采用了Yuriy Vinogradov在另一个回答中提供的代码,并且那似乎有效。 - blueice
如何更改Drawable而不是更改颜色? - Iman Marashi
@ImanMarashi 请参考Alex的基于XML的答案,LayerDrawable.setDrawable(index, drawable)仅适用于API23及以上版本。 - Dan Dar3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接