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()

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

相关推荐
XLYcmy15 分钟前
HTML/CSS/JS 基础与 Vue 技术栈深度解析
java·前端·css·html·vue3·vue2·api
新知图书35 分钟前
12.3 智能体中Skill的约束与自进化实战
java·前端·数据库
风月说与山鬼37 分钟前
四、Tailwind CSS——间距与尺寸
前端·css·tailwind css
en.en..43 分钟前
C语言 static函数与头文件封装规范
java·c语言·前端
计算机魔术师1 小时前
旅途中用手机远程控制电脑?电脑不在身边,ToDesk/UU远程/TeamViewer移动端深度实测
前端
风月说与山鬼1 小时前
三、Tailwind CSS——排版与文字样式
前端·css·tailwind css
eokred1 小时前
图片预览组件的另一种设计:Headless、可组合、开箱即用
前端·react
南雨北斗1 小时前
解决web开发中前后端跨域通信(session失效问题)
前端
Y3815326621 小时前
body-upload-js
前端·javascript·浏览器·深拷贝·数据克隆