RatingBar,Android系统原生的评分控件,类似淘宝一类的电商APP在购买支付,确认付款之后都会有评价和评星级(评分的)功能,也可以用这个去实现。
在Android的帮助文档中是这么说的 :RatingBar是基于SeekBar和ProgressBar的扩展,用星型来显示等级评定。使用RatingBar的默认大小时,用户可以触摸/拖动或使用键来设置评分,它有两种样式(小风格用ratingBarStyleSmall,大风格用ratingBarStyleIndicator),其中大的只适合指示(根据你提供的数据,显示具体的星级),不与用户交互。当使用可以支持用户交互的RatingBar时,无论将控件(widgets)放在它的左边还是右边都是不合适的。只有当布局的宽被设置为wrap content时,设置的星星数量(通过函数setNumStars(int)或者在XML的布局文件中定义)将显示出来(如果设置为另一种布局宽的话,后果无法预知)。次级进度(类似进度条里面二级进度)一般不应该被修改,因为他仅仅是被当作星型部分内部的填充背景。
先看RatingBar的一般效果图(懒得自己从手机上截取动态度了),就随便copy一张:
在layout文件中添加RatingBar有一些相关的属性需要熟悉一下:
属性名称 | 描述 |
android:isIndicator | RatingBar是否是一个指示器(不与用户交互) |
android:numStars | 显示的星型数量,必须是一个整形值,像“100”。 |
android:rating | 默认的评分,必须是浮点类型,像“1.2”。 |
android:stepSize | 评分的步长,必须是浮点类型,像“1”。 |
写这边文章,主要是想记录一下自己所走过的坑,让自己以后有据可查,也希望帮到需要用到RatingBar空间的人,避免这些坑。
在RatingBar的官方API中有这么两个方法public void setRating(float rating) ,父类继承过来的setProgress(int progress).这两个方法 在我们使用的时候都能够达到显示星级评分的效果但是有一些需要注意,这2个方法与API当中的setMax(int max) setStepSize(float size),默认的时候我们的评分星级的stars数量是5个,但是我们可以通过setNumberStars设置我们需要展示的stars数量。
假如我们看下面3行代码(XML代码 和其他逻辑代码省略):
bar.setStepSize(0.1f);
bar.setMax(5);
bar.setRating(4.1f);
首先设置了步长位0.1,在设置星星最多为5个,这两行代码的意思就是说,假如我们的进度条的速度位0.1颗星/秒,我们进度条走完需要50秒,我么设置setRating(4.1f),理论上的显示效果应该是前面4颗星全部显示位上面我们图片所示的“亮色”,第五颗星只有最左边那么一点(10% 即0.1)显示“亮色”,其他显示背景色。其实并不然 ,最后结果只有前4颗星是“亮色”,最后一颗星是暗色。why?看看源代码中怎么写的。
public void setRating(float rating) {
setProgress(Math.round(rating * getProgressPerStar()));
}
getProgressPerStar函数
/**
* @return The amount of progress that fits into a star
*/
private float getProgressPerStar() {
if (mNumStars > 0) {
return 1f * getMax() / mNumStars;
} else {
return 1;
}
}
先解释
getProgressPerStar(),字面意思就是每颗心表示的进度,默认情况下我们的mNumStars=5(没有自己设置的情况下),那函数最后返回的是1f*getMax()/mNumStars,在上面的代码中结果就是一颗星的进度表示为1(1进度/每颗星),总共5颗星,按照数学逻辑是五颗星总进度是1(100%),那么一颗星就是20%.上面步长0.1,rating为4.1总进度应该为4*20%+0.1*20%=82% 可是现实效果只有4颗星(80%) ,这是为什么?我们仔细看setRating(float rating)函数的具体实现,最后实质上调用的是父类的setProgress()方法,只是传入的参数是经过数学处理的Math.round,而在java的api函数round的意思是round方法,它表示“四舍五入”,算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,上面我们设置的为4.1f最后成Math.round(4.1*1) 按照上面所说他的结果位Math.floor(4.6)向下取整,即为4,也就是说我们设置的最后是setProgress(4),也就显示4颗星为"亮色'了。
由于我们所调用的父类函数setProgress(int) 参数必须是int类型。假设我们有下面一段代码
bar.setStepSize(1f);
bar.setMax(100);
bar.setProgress(82);
// bar.setRating(4.1f);
这max位100,那么每颗星展百分比(5颗星按100%制计算)20%。setProgress(82)其实和setRating(4.1f)达到的效果是一样的。就相当于等比率的计算82/100=4.1/5。就只需要记住max和progress对应,Rating和星星个数mNumstars对应。由于setProgress的参数只能位整数,setRating的向下取整。在我们将RatingBar作为指示控件(仅仅显示,不与用户交互)的时候需要注意,适当的时候我们可以等倍数的放大,设置setMax的值。这个问题到此结束。
还有一个问题就是自定义的Rating。说实质的这里自定义RatingBar其实很简单,就是位RatingBar添加一个style文件,让它不使用系统原生态的style,我们就可以达到我们显示的效果了。
亮色star_selected(为了显示效果放大了) 暗色star_unselected(背景色)
只需要自定义一个drawable对象,例如下面
<?xml version="1.0" encoding="utf-8"?>
<!-- This is the rating bar drawable that is used to show a room num.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+android:id/background"
android:drawable="@drawable/star_unselected">
</item>
<item
android:id="@+android:id/secondaryProgress"
android:drawable="@drawable/star_unselected">
</item>
<item
android:id="@+android:id/progress"
android:drawable="@drawable/star_selected">
</item>
</layer-list>
我们在使用的时候只需要将drawable应用于RatingBar就ok,应用于progressDrawable属性就ok。
<RatingBar
android:id="@+id/room_ratingbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:isIndicator="true"
android:progressDrawable="@drawable/rating_bar" >
</RatingBar>
其实自定义RatingBar就是改变一下我们“亮色”和“暗色”的背景图片就ok。
哈哈,写完了,由于比较简单,也没有截图和提交代码,里面也没有将API文档上和网上都能查到的函数,回调接口函数列出来,大家需要的时候再查文档或者问度娘就ok。仅供大家参考。