Skip to content

Instantly share code, notes, and snippets.

@jefisu
Forked from vitorprado/RatingBar.kt
Last active July 16, 2022 18:52
Show Gist options
  • Save jefisu/d7234cef6bb80269d64f04d7bc18619e to your computer and use it in GitHub Desktop.
Save jefisu/d7234cef6bb80269d64f04d7bc18619e to your computer and use it in GitHub Desktop.
Jetpack Compose RatingBar (alpha12)
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.GenericShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.jefisu.movieapp.ui.theme.LocalSpacing
import kotlin.math.cos
import kotlin.math.sin
@Composable
fun RatingBar(
rating: Float,
modifier: Modifier = Modifier,
height: Dp = 20.dp,
color: Color = Color.Yellow
) {
Row(
modifier = Modifier
.height(height)
.wrapContentSize()
.then(modifier),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
(1..5).forEach { step ->
val stepRating = when {
rating > step -> 1f
step.rem(rating) < 1 -> rating - (step - 1f)
else -> 0f
}
RatingStar(stepRating, color)
}
}
}
@Composable
private fun RatingStar(
rating: Float,
ratingColor: Color = Color.Yellow,
backgroundColor: Color = Color.Gray
) {
val starPath = { size: Float ->
Path().apply {
val outerRadius: Float = size / 1.8f
val innerRadius: Double = outerRadius / 2.5
var rot: Double = Math.PI / 2 * 3
val cx: Float = size / 2
val cy: Float = size / 20 * 11
var x: Float = cx
var y: Float = cy
val step = Math.PI / 5
moveTo(cx, cy - outerRadius)
repeat(5) {
x = (cx + cos(rot) * outerRadius).toFloat()
y = (cy + sin(rot) * outerRadius).toFloat()
lineTo(x, y)
rot += step
x = (cx + cos(rot) * innerRadius).toFloat()
y = (cy + sin(rot) * innerRadius).toFloat()
lineTo(x, y)
rot += step
}
close()
}
}
val starShape = GenericShape { size, _ ->
addPath(starPath(size.height))
}
BoxWithConstraints(
modifier = Modifier
.fillMaxHeight()
.aspectRatio(1f)
.clip(starShape)
) {
Canvas(modifier = Modifier.size(maxHeight)) {
drawRect(
brush = SolidColor(backgroundColor),
size = Size(
height = size.height * 1.4f,
width = size.width * 1.4f
),
topLeft = Offset(
x = -(size.width * 0.1f),
y = -(size.height * 0.1f)
)
)
if (rating > 0) {
drawRect(
brush = SolidColor(ratingColor),
size = Size(
height = size.height * 1.1f,
width = size.width * rating
)
)
}
}
}
}
@Preview
@Composable
fun RatingBarPreview() {
Box(modifier = Modifier.padding(8.dp)) {
RatingBar(
rating = 3.8f,
height = 25.dp
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment