Skip to content

Instantly share code, notes, and snippets.

@V-Abhilash-1999
Created May 23, 2023 12:25
Show Gist options
  • Save V-Abhilash-1999/cb7d6af1f3a565b792bea31f688195b7 to your computer and use it in GitHub Desktop.
Save V-Abhilash-1999/cb7d6af1f3a565b792bea31f688195b7 to your computer and use it in GitHub Desktop.
HueBar
@Composable
fun HueBar(
setColor: (Float) -> Unit
) {
val scope = rememberCoroutineScope()
val interactionSource = remember {
MutableInteractionSource()
}
val pressOffset = remember {
mutableStateOf(Offset.Zero)
}
Canvas(
modifier = Modifier
.height(40.dp)
.width(300.dp)
.clip(RoundedCornerShape(50))
.emitDragGesture(interactionSource)
) {
val drawScopeSize = size
val bitmap = Bitmap.createBitmap(size.width.toInt(), size.height.toInt(), Bitmap.Config.ARGB_8888)
val hueCanvas = Canvas(bitmap)
val huePanel = RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat())
val hueColors = IntArray((huePanel.width()).toInt())
var hue = 0f
for (i in hueColors.indices) {
hueColors[i] = AndroidColor.HSVToColor(floatArrayOf(hue, 1f, 1f))
hue += 360f / hueColors.size
}
val linePaint = Paint()
linePaint.strokeWidth = 0F
for (i in hueColors.indices) {
linePaint.color = hueColors[i]
hueCanvas.drawLine(i.toFloat(), 0F, i.toFloat(), huePanel.bottom, linePaint)
}
drawBitmap(
bitmap = bitmap,
panel = huePanel
)
fun pointToHue(pointX: Float): Float {
val width = huePanel.width()
val x = when {
pointX < huePanel.left -> 0F
pointX > huePanel.right -> width
else -> pointX - huePanel.left
}
return x * 360f / width
}
scope.collectForPress(interactionSource) { pressPosition ->
val pressPos = pressPosition.x.coerceIn(0f..drawScopeSize.width)
pressOffset.value = Offset(pressPos, 0f)
val selectedHue = pointToHue(pressPos)
setColor(selectedHue)
}
drawCircle(
Color.White,
radius = size.height/2,
center = Offset(pressOffset.value.x, size.height/2),
style = Stroke(
width = 2.dp.toPx()
)
)
}
}
fun CoroutineScope.collectForPress(
interactionSource: InteractionSource,
setOffset: (Offset) -> Unit
) {
launch {
interactionSource.interactions.collect { interaction ->
(interaction as? PressInteraction.Press)
?.pressPosition
?.let(setOffset)
}
}
}
private fun Modifier.emitDragGesture(
interactionSource: MutableInteractionSource
): Modifier = composed {
val scope = rememberCoroutineScope()
pointerInput(Unit) {
detectDragGestures { input, _ ->
scope.launch {
interactionSource.emit(PressInteraction.Press(input.position))
}
}
}.clickable(interactionSource, null) {
}
}
private fun DrawScope.drawBitmap(
bitmap: Bitmap,
panel: RectF
) {
drawIntoCanvas {
it.nativeCanvas.drawBitmap(
bitmap,
null,
panel.toRect(),
null
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment