Created
June 8, 2024 18:00
-
-
Save YohannesTz/1a4a1946b620c6ee11d9e7fa08e92a2b to your computer and use it in GitHub Desktop.
RatingView for android that has an emoji effect
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.github.yohannestz.visionedu.view.customview | |
import android.annotation.SuppressLint | |
import android.content.Context | |
import android.graphics.* | |
import android.util.AttributeSet | |
import android.view.View | |
class RatingView @JvmOverloads constructor( | |
context: Context, | |
attrs: AttributeSet? = null, | |
defStyleAttr: Int = 0 | |
) : View(context, attrs, defStyleAttr) { | |
private var sliderValue: Float = 0.2f | |
private val paint = Paint(Paint.ANTI_ALIAS_FLAG) | |
// Setter for sliderValue | |
fun setSliderValue(value: Float) { | |
sliderValue = value.coerceIn(0.2f, 1f) | |
invalidate() // Redraw the view | |
} | |
@SuppressLint("DrawAllocation") | |
override fun onDraw(canvas: Canvas) { | |
super.onDraw(canvas) | |
val width = width.toFloat() | |
val height = height.toFloat() | |
// Center and radius | |
val centerX = width / 2 | |
val centerY = height / 2 | |
val radius = width.coerceAtMost(height) / 3 | |
// Dynamic color based on sliderValue | |
val startColor = Color.parseColor("#fc4e03") | |
val endColor = Color.parseColor("#ffb803") | |
val dynamicColor = lerpColor(startColor, endColor, sliderValue) | |
// Draw the face | |
paint.color = dynamicColor | |
paint.style = Paint.Style.FILL | |
canvas.drawCircle(centerX, centerY, radius, paint) | |
if (sliderValue < 0.5) { | |
// Draw eyes | |
paint.color = Color.BLACK | |
paint.style = Paint.Style.FILL | |
canvas.drawCircle(centerX - 40f, centerY - 40f, 8f, paint) | |
canvas.drawCircle(centerX + 40f, centerY - 40f, 8f, paint) | |
} else { | |
val tiltAngle = (sliderValue - 0.5f) * 0.2f | |
// Draw V-shaped eyes | |
drawVShape(canvas, centerX - 40f, centerY - 40f, tiltAngle) | |
drawVShape(canvas, centerX + 40f, centerY - 40f, tiltAngle) | |
// Draw blush | |
paint.style = Paint.Style.FILL | |
paint.shader = createRadialGradient(centerX - 50f, centerY + 10f, 20f, startColor, endColor) | |
canvas.drawCircle(centerX - 50f, centerY + 10f, 20f, paint) | |
paint.shader = createRadialGradient(centerX + 50f, centerY + 10f, 20f, startColor, endColor) | |
canvas.drawCircle(centerX + 50f, centerY + 10f, 20f, paint) | |
paint.shader = null | |
} | |
// Draw mouth | |
paint.color = Color.BLACK | |
paint.style = Paint.Style.STROKE | |
paint.strokeWidth = 4f | |
val rectF = RectF(centerX - 30f, centerY - 5f, centerX + 30f, centerY - 5f + sliderValue * 50f) | |
canvas.drawArc(rectF, 0f, 180f, false, paint) | |
} | |
private fun createRadialGradient(centerX: Float, centerY: Float, radius: Float, startColor: Int, endColor: Int): RadialGradient { | |
return RadialGradient( | |
centerX, centerY, radius, | |
intArrayOf(Color.parseColor("#fc4e03"), lerpColor(startColor, endColor, sliderValue)), | |
null, Shader.TileMode.CLAMP | |
) | |
} | |
private fun drawVShape(canvas: Canvas, x: Float, y: Float, tiltAngle: Float) { | |
val lineLength = 15f | |
paint.color = Color.BLACK | |
paint.style = Paint.Style.STROKE | |
paint.strokeWidth = 10f | |
val xOffset = lineLength * tiltAngle | |
val yOffset = lineLength * tiltAngle | |
canvas.drawLine(x - lineLength + xOffset, y + lineLength + yOffset, x, y, paint) | |
canvas.drawLine(x, y, x + lineLength + xOffset, y + lineLength + yOffset, paint) | |
} | |
private fun lerpColor(startColor: Int, endColor: Int, fraction: Float): Int { | |
val startR = Color.red(startColor) | |
val startG = Color.green(startColor) | |
val startB = Color.blue(startColor) | |
val startA = Color.alpha(startColor) | |
val endR = Color.red(endColor) | |
val endG = Color.green(endColor) | |
val endB = Color.blue(endColor) | |
val endA = Color.alpha(endColor) | |
val r = (startR + fraction * (endR - startR)).toInt() | |
val g = (startG + fraction * (endG - startG)).toInt() | |
val b = (startB + fraction * (endB - startB)).toInt() | |
val a = (startA + fraction * (endA - startA)).toInt() | |
return Color.argb(a, r, g, b) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment