通过自定义RatingBar的样式实现⭐️⭐️⭐️指示器的方式功能过于受限,而且显示的样式阴影会受到影响。
系统自带显示:
自定义样式:
因此简单自一个符合要求的 CustomRatingBar
- 支持设置星星数量
- 支持设置星星Rating(float)
- 支持设置空显示
- 支持设置半空显示
- 支持设置全显示
- 支持设置星星之间的间距
- 支持设置星星的宽高
1. 创建自定义 RatingBar 类
首先,创建一个自定义的 RatingBar 类,继承自 View,并重写相关方法。
import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import com.example.yourapp.R
class CustomRatingBar @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private var starCount = 5 // 星星数量
private var rating = 0f // 当前评分
private var starSpacing = 0 // 星星间距
private var starWidth = 0 // 星星宽度
private var starHeight = 0 // 星星高度
private var starEmptyDrawable: Drawable? = null
private var starHalfDrawable: Drawable? = null
private var starFullDrawable: Drawable? = null
init {
val a = context.theme.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar, 0, 0)
try {
starCount = a.getInteger(R.styleable.CustomRatingBar_starCount, starCount)
rating = a.getFloat(R.styleable.CustomRatingBar_rating, rating)
starSpacing = a.getDimensionPixelSize(R.styleable.CustomRatingBar_starSpacing, starSpacing)
starWidth = a.getDimensionPixelSize(R.styleable.CustomRatingBar_starWidth, 0)
starHeight = a.getDimensionPixelSize(R.styleable.CustomRatingBar_starHeight, 0)
starEmptyDrawable = a.getDrawable(R.styleable.CustomRatingBar_starEmpty)
starHalfDrawable = a.getDrawable(R.styleable.CustomRatingBar_starHalf)
starFullDrawable = a.getDrawable(R.styleable.CustomRatingBar_starFull)
} finally {
a.recycle()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val width: Int
val height: Int
if (starWidth > 0) {
width = starWidth * starCount + starSpacing * (starCount - 1)
} else {
width = MeasureSpec.getSize(widthMeasureSpec)
starWidth = (width - starSpacing * (starCount - 1)) / starCount
}
height = if (starHeight > 0) {
starHeight
} else {
starWidth
}
setMeasuredDimension(width, height)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (starEmptyDrawable == null || starHalfDrawable == null || starFullDrawable == null) {
return
}
for (i in 0 until starCount) {
val starRating = rating - i
val drawable = when {
starRating >= 1 -> starFullDrawable
starRating >= 0.5 -> starHalfDrawable
else -> starEmptyDrawable
}
val left = i * (starWidth + starSpacing)
val right = left + starWidth
drawable?.setBounds(left, 0, right, height)
drawable?.draw(canvas)
}
}
fun setRating(rating: Float) {
this.rating = rating
invalidate()
}
fun getRating(): Float = rating
fun setStarCount(starCount: Int) {
this.starCount = starCount
requestLayout()
invalidate()
}
fun getStarCount(): Int = starCount
fun setStarSpacing(spacing: Int) {
this.starSpacing = spacing
requestLayout()
invalidate()
}
fun getStarSpacing(): Int = starSpacing
fun setStarWidth(width: Int) {
this.starWidth = width
requestLayout()
invalidate()
}
fun getStarWidth(): Int = starWidth
fun setStarHeight(height: Int) {
this.starHeight = height
requestLayout()
invalidate()
}
fun getStarHeight(): Int = starHeight
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP -> {
val newRating = (event.x / width * starCount).toInt() + 1
setRating(newRating.toFloat())
return true
}
}
return super.onTouchEvent(event)
}
}
2. 自定义属性
在 res/values/attrs.xml 文件中添加星星宽高的自定义属性:
<declare-styleable name="CustomRatingBar">
<attr name="starCount" format="integer" />
<attr name="rating" format="float" />
<attr name="starSpacing" format="dimension" />
<attr name="starWidth" format="dimension" />
<attr name="starHeight" format="dimension" />
<attr name="starEmpty" format="reference" />
<attr name="starHalf" format="reference" />
<attr name="starFull" format="reference" />
</declare-styleable>
3. 使用自定义 RatingBar
在你的布局文件中使用自定义的 CustomRatingBar 并设置星星宽高和间距:
<com.example.yourapp.CustomRatingBar
android:id="@+id/customRatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:starCount="5"
app:rating="3.5"
app:starSpacing="8dp"
app:starWidth="40dp"
app:starHeight="40dp"
app:starEmpty="@drawable/star_empty"
app:starHalf="@drawable/star_half"
app:starFull="@drawable/star_full" />
4. 在代码中设置星级、间距、宽度和高度
在你的 Activity 或 Fragment 中设置星级、星星间距、宽度和高度:
val ratingBar: CustomRatingBar = findViewById(R.id.customRatingBar)
ratingBar.setRating(4.0f)
ratingBar.setStarSpacing(16) // 设置星星间距为16像素
ratingBar.setStarWidth(60) // 设置星星宽度为60像素
ratingBar.setStarHeight(60) // 设置星星高度为60像素
这样就完成了一个支持设置星星数量、三种状态、星星之间间距以及星星宽高的自定义 RatingBar 指示器。