Skip to content

Instantly share code, notes, and snippets.

@skaldebane
Last active April 22, 2025 01:34
Show Gist options
  • Select an option

  • Save skaldebane/fea5c8c24193c7b05c7f5bbd099a100b to your computer and use it in GitHub Desktop.

Select an option

Save skaldebane/fea5c8c24193c7b05c7f5bbd099a100b to your computer and use it in GitHub Desktop.
WaniKani radical/kanji/vocab/reading highlight colors for Compose.
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.*
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize
import androidx.compose.ui.window.singleWindowApplication
fun main() = singleWindowApplication {
val density = LocalDensity.current
val textMeasurer = rememberTextMeasurer()
val text = buildAnnotatedString {
append("Testing: ")
appendInlineContent(id = "radical-0", alternateText = "radical")
append("s, ")
appendInlineContent(id = "kanji-0", alternateText = "kanji")
append(", ")
appendInlineContent(id = "radical-1", alternateText = "another radical")
append(", ")
appendInlineContent(id = "vocab-0", alternateText = "vocab")
append(", and ")
appendInlineContent(id = "reading-0", alternateText = "reading")
append("s.")
}
val style = LocalTextStyle.current
Text(
text = text,
style = style,
inlineContent = buildMap {
val annotations = text.getStringAnnotations(
tag = "androidx.compose.foundation.text.inlineContent",
start = 0, end = text.length
)
for (annotation in annotations) {
val layoutResult = textMeasurer.measure(
text = text.slice(annotation.start..<annotation.end).toString(),
style = style.merge(
color = Color.White,
shadow = Shadow(
color = Color.Black.copy(.2f),
offset = with(density) { Offset(x = 0f, y = 1.dp.toPx()) }
)
)
)
val placeholderSize = with(density) { layoutResult.size.toSize().toDpSize() }
val placeholder = with(density) {
Placeholder(
width = ((placeholderSize.width + 8.dp).value / fontScale).sp,
height = ((placeholderSize.width + 2.dp).value / fontScale).sp,,
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
)
}
this[annotation.item] = InlineTextContent(placeholder) {
val type = annotation.item.substringBefore("-")
Canvas(
modifier = Modifier
.drawBehind {
drawRoundRect(
color = when (type) {
"radical" -> Color.Black.copy(alpha = 0.2f).compositeOver(Color(0xFF0093DD))
"kanji" -> Color.Black.copy(alpha = 0.2f).compositeOver(Color(0xFFDD0093))
"vocab" -> Color.Black.copy(alpha = 0.2f).compositeOver(Color(0xFF9300DD))
else -> Color.Black.copy(alpha = 0.2f).compositeOver(Color(0xFF484848))
},
cornerRadius = CornerRadius(x = 4.dp.toPx(), y = 4.dp.toPx()),
)
drawRoundRect(
brush = when (type) {
"radical" -> Brush.verticalGradient(listOf(Color(0xFF00AAFF), Color(0xFF0093DD)))
"kanji" -> Brush.verticalGradient(listOf(Color(0xFFFF00AA), Color(0xFFDD0093)))
"vocab" -> Brush.verticalGradient(listOf(Color(0xFFAA00FF), Color(0xFF9300DD)))
else -> Brush.verticalGradient(listOf(Color(0xFF505050), Color(0xFF484848)))
},
cornerRadius = CornerRadius(x = 4.dp.toPx(), y = 4.dp.toPx()),
size = size.copy(height = size.height - 2.dp.toPx()),
)
}
.padding(horizontal = 4.dp, vertical = 1.dp)
.size(placeholderSize)
) {
drawText(layoutResult)
}
}
}
}
)
}
@skaldebane
Copy link
Copy Markdown
Author

Ah, this isn't material specific at all. I think the only thing I pulled from Material was the Text composable, as well as LocalTextStyle, so just replace them with whatever equivalents exist in Material 3 (in case of LocalTextStyle, you don't necessarily have to use it per se, just use the same TextStyle you do for the rest of the text).

@codejockie
Copy link
Copy Markdown

Nevermind, got it.

@codejockie
Copy link
Copy Markdown

Nice job, and very well done and explained!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment