Skip to content

Instantly share code, notes, and snippets.

@bentrengrove
Last active November 28, 2022 09:16
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bentrengrove/c2bdc85c7c4e2eca1905b0da2d5ff810 to your computer and use it in GitHub Desktop.
Save bentrengrove/c2bdc85c7c4e2eca1905b0da2d5ff810 to your computer and use it in GitHub Desktop.
MatrixText.kt - A Composeable that displays text Matrix style down the screen
private const val MAX_SPEED = 25
private const val MIN_SPEED = 7
private const val MAX_FONT_SIZE = 64f
private const val MIN_FONT_SIZE = 24f
private val characters = listOf("", "", "", "", "", "", "", "", "")
private val colors = listOf(0xffcefbe4, 0xff81ec72, 0xff5cd646, 0xff54d13c, 0xff4ccc32, 0xff43c728)
@Composable
fun MatrixText(
stripCount: Int = 25,
lettersPerStrip: Int = 20,
modifier: Modifier = Modifier
) {
// Where each strip is in Y
// Drive composition with this state
val stripY = remember { mutableStateListOf<Int>() }
// Where each strip is in X
val stripX = remember { IntArray(stripCount).toMutableList() }
// The speed of each strip
val dY = remember { IntArray(stripCount).toMutableList() }
// The font size of each strip
val stripFontSize = remember { IntArray(stripCount).toMutableList() }
val paint = Paint().asFrameworkPaint().apply {
isAntiAlias = true
typeface = Typeface.SANS_SERIF
}
Canvas(
modifier
.fillMaxSize()
.background(Color.Black)) {
val width = size.width
val height = size.height
for (i in 0 until stripCount) {
var y = stripY.getOrNull(i)
paint.textSize = stripFontSize[i].toFloat()
if (y == null || (y > height + (lettersPerStrip * stripFontSize[i]))) {
if (y == null) {
stripY.add(0)
}
// Initialise a strip in a random location
stripX[i] = (Random.nextFloat() * width).toInt()
stripY[i] = -99 // Start off screen
dY[i] = ((Random.nextFloat() * MAX_SPEED.dp.value) + MIN_SPEED.dp.value).toInt()
stripFontSize[i] = ((Random.nextFloat() * MAX_FONT_SIZE) + MIN_FONT_SIZE).toInt()
} else {
val x = stripX[i]
(0 until lettersPerStrip).forEach { _ ->
val randChar = characters.random()
paint.color = colors.random().toInt()
drawIntoCanvas {
it.nativeCanvas.drawText(randChar, x.toFloat(), y.toFloat(), paint)
}
y -= stripFontSize[i]
}
}
}
}
LaunchedEffect(key1 = Unit) {
while(true) {
delay(60)
for (i in 0 until stripCount) {
// Increase the start position of each strip which will trigger a recomposition
stripY[i] = stripY[i] + dY[i]
}
}
}
}
private fun<T> SnapshotStateList<T>.getOrNull(index: Int): T? {
if (index < 0 || index >= size) return null
return get(index)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment