You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose真的无RatingBar?需实现可交互星级评分控件

实现Jetpack Compose交互式星级评分组件

以下是一个可直接使用的交互式星级评分条实现,支持点击、滑动调整评分,完全基于Jetpack Compose原生API编写:

import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Star
import androidx.compose.material.icons.outlined.Star
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp

@Composable
fun InteractiveRatingBar(
    modifier: Modifier = Modifier,
    starCount: Int = 5,
    starSize: Dp = 24.dp,
    filledStarColor: Color = Color(0xFFFFD700),
    emptyStarColor: Color = Color.Gray,
    initialRating: Float = 0f,
    onRatingChanged: (Float) -> Unit
) {
    var currentRating by remember { mutableStateOf(initialRating.coerceIn(0f, starCount.toFloat())) }

    Box(
        modifier = modifier
            .pointerInput(Unit) {
                // 处理点击事件
                detectTapGestures { offset ->
                    val newRating = (offset.x / size.width) * starCount
                    currentRating = newRating.coerceIn(0f, starCount.toFloat())
                    onRatingChanged(currentRating)
                }
                // 处理滑动事件
                detectHorizontalDragGestures { change, _ ->
                    val touchX = change.position.x.coerceIn(0f, size.width)
                    val newRating = (touchX / size.width) * starCount
                    currentRating = newRating.coerceIn(0f, starCount.toFloat())
                    onRatingChanged(currentRating)
                }
            },
        contentAlignment = Alignment.CenterStart
    ) {
        Row {
            repeat(starCount) { index ->
                val starFraction = when {
                    currentRating >= index + 1 -> 1f
                    currentRating > index -> currentRating - index
                    else -> 0f
                }

                Icon(
                    imageVector = Icons.Outlined.Star,
                    contentDescription = "Empty star ${index + 1}",
                    tint = emptyStarColor,
                    modifier = modifier.size(starSize)
                )

                if (starFraction > 0) {
                    Box(Modifier.size(starSize).align(Alignment.CenterStart)) {
                        Icon(
                            imageVector = Icons.Filled.Star,
                            contentDescription = "Filled star ${index + 1}",
                            tint = filledStarColor,
                            modifier = Modifier.size(starSize * starFraction)
                        )
                    }
                }
            }
        }
    }
}

使用示例

@Composable
fun RatingScreen() {
    var rating by remember { mutableStateOf(2.5f) }

    InteractiveRatingBar(
        initialRating = rating,
        starCount = 5,
        starSize = 32.dp,
        onRatingChanged = { newRating ->
            rating = newRating
            // 这里可以处理评分变更后的逻辑,比如保存到ViewModel
        }
    )
}

核心功能说明

  • 支持点击和水平滑动两种交互方式调整评分
  • 支持半星显示,通过计算触摸位置对应的星级比例实现
  • 可自定义星级数量、大小、填充/未填充颜色
  • 自动限制评分范围在0到设定的星级数量之间
  • 实时回调更新后的评分值

扩展优化建议

  1. 可以添加动画效果,比如评分变更时的星级填充动画
  2. 支持设置最小评分步长(比如只允许整数评分)
  3. 添加触摸反馈(比如波纹效果)提升交互体验

内容的提问来源于stack exchange,提问作者Marty Miller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 22:27:09