通过自定义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.Rclass 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? = nullprivate var starHalfDrawable: Drawable? = nullprivate var starFullDrawable: Drawable? = nullinit {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: Intval height: Intif (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 - ival drawable = when {starRating >= 1 -> starFullDrawablestarRating >= 0.5 -> starHalfDrawableelse -> starEmptyDrawable}val left = i * (starWidth + starSpacing)val right = left + starWidthdrawable?.setBounds(left, 0, right, height)drawable?.draw(canvas)}}fun setRating(rating: Float) {this.rating = ratinginvalidate()}fun getRating(): Float = ratingfun setStarCount(starCount: Int) {this.starCount = starCountrequestLayout()invalidate()}fun getStarCount(): Int = starCountfun setStarSpacing(spacing: Int) {this.starSpacing = spacingrequestLayout()invalidate()}fun getStarSpacing(): Int = starSpacingfun setStarWidth(width: Int) {this.starWidth = widthrequestLayout()invalidate()}fun getStarWidth(): Int = starWidthfun setStarHeight(height: Int) {this.starHeight = heightrequestLayout()invalidate()}fun getStarHeight(): Int = starHeightoverride fun onTouchEvent(event: MotionEvent): Boolean {when (event.action) {MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP -> {val newRating = (event.x / width * starCount).toInt() + 1setRating(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.CustomRatingBarandroid: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 指示器。