Kotlin中实现星级评价选择功能(仅支持整数)

效果图

1.在res下values添加attr.xml

XML 复制代码
        <declare-styleable name="CustomRatingBar">
            <attr name="starCount" format="integer" /><!-- 总共有几颗星-->
            <attr name="rating" format="float" /><!-- 默认选择几颗星-->
            <attr name="starSpacing" format="dimension" /><!--padding值-->
            <attr name="starEmpty" format="reference" /><!--选中后的图片-->
            <attr name="starFull" format="reference" /><!--未选中时的图片-->
        </declare-styleable>

2.自定义View(支持手势左右滑动选中)

Kotlin 复制代码
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.widget.ImageView
import android.widget.LinearLayout

class CustomRatingBar @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {

    private var starCount = 5
    var currentRating = 0f
    var mRating = 0f
    private var starSpacing = 8
    private val starViews = mutableListOf<ImageView>()

    init {
        orientation = HORIZONTAL
        gravity = Gravity.CENTER_VERTICAL
        // 解析 XML 中的自定义属性
        context.obtainStyledAttributes(attrs, R.styleable.CustomRatingBar).apply {
            starCount = getInt(R.styleable.CustomRatingBar_starCount, 5)
            currentRating = getFloat(R.styleable.CustomRatingBar_rating, 0f)
            mRating = getFloat(R.styleable.CustomRatingBar_rating, 0f)
            starSpacing = getDimensionPixelSize(R.styleable.CustomRatingBar_starSpacing, 8)
            recycle()
        }
        initStars()
    }

    private fun initStars() {
        removeAllViews()
        for (i in 0 until starCount) {
            val star = ImageView(context).apply {
                layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
                    if (i > 0) leftMargin = starSpacing
                }
                setOnClickListener { setRating((i + 1).toFloat()) }
            }
            addView(star)
            starViews.add(star)
        }
        updateStars()
    }

    fun setRating(rating: Float) {
        currentRating = rating.coerceIn(mRating, starCount.toFloat())
        updateStars()
    }

    private fun updateStars() {
        starViews.forEachIndexed { index, imageView ->
            //向左滑动最少显示指定的默认选中数量
            val resId = if (index < currentRating || (index==0&&currentRating==mRating)) R.mipmap.star_true else R.mipmap.star_false
            imageView.setImageResource(resId)
        }
    }

    // 支持手指滑动评分
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
                val newRating = (event.x / width * starCount).toInt() + 1
                setRating(newRating.toFloat())
                return true
            }
        }
        return super.onTouchEvent(event)
    }
}

3.xml中使用

XML 复制代码
	<LinearLayout
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/black"
            android:textSize="15dp"
            android:text="星级评分:"/>
        <CustomRatingBar
            android:id="@+id/customRatingBar"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            app:starCount="5"
            app:rating="1"
            app:starSpacing="12dp"
            app:starEmpty="@mipmap/star_true"
            app:starFull="@mipmap/star_false" />
    </LinearLayout>

4.代码中获取当前选中几颗星

XML 复制代码
val choose = binding.customRatingBar.currentRating.toInt()

图片元素(效果图中使用的图片,可替换自己的)

相关推荐
该用户已成仙2 小时前
vue3 使用 vuedraggable 报错 TypeError: isFunction2 is not a function
前端·javascript·vue.js
良逍Ai出海2 小时前
我用 Codex 搭了一个 WordPress 独立站
前端
TPBoreas2 小时前
前端面试问题打把-场景题
开发语言·前端·javascript
问心无愧05132 小时前
ctf show web入门159
前端·笔记
恋猫de小郭2 小时前
Flutter 又为 AI 时代添砖加瓦:全新 ComponentLibrary 提议
android·前端·flutter
就叫_这个吧2 小时前
HTML或JSP页面链接CSS,link标签没问题,但不显示样式问题解决
java·前端·css·html·intellij-idea·jsp
IT_陈寒2 小时前
SpringBoot这个坑差点让我加班到天亮
前端·人工智能·后端
小小龙学IT3 小时前
Rust Web 框架 Axum:轻量级异步的下一代后端利器
前端·驱动开发·rust
大鱼前端3 小时前
10 分钟用 Bun + Hono + SQLite 跑通一个全栈 API
前端·javascript