Skip to content

Instantly share code, notes, and snippets.

@mertceyhan
Created May 8, 2023 13:54
Show Gist options
  • Save mertceyhan/9cbce75a0c232a9bff20622d8d915640 to your computer and use it in GitHub Desktop.
Save mertceyhan/9cbce75a0c232a9bff20622d8d915640 to your computer and use it in GitHub Desktop.
TypewriterTextEffect: A customizable Jetpack Compose function that reveals text with a typewriter-like effect, one chunk at a time
/**
* A composable function that displays a text with a typewriter-like effect, revealing characters in chunks.
*
* @param text The input text to be displayed with the typewriter effect.
* @param minDelayInMillis The minimum delay in milliseconds between revealing character chunks, defaults to 10ms.
* @param maxDelayInMillis The maximum delay in milliseconds between revealing character chunks, defaults to 50ms.
* @param minCharacterChunk The minimum number of characters to reveal at once, defaults to 1.
* @param maxCharacterChunk The maximum number of characters to reveal at once, defaults to 5.
* @param onEffectCompleted A callback function invoked when the entire text has been revealed.
* @param displayTextComposable A composable function that receives the text to display with the typewriter effect.
*
* @throws IllegalArgumentException if [minDelayInMillis] is greater than [maxDelayInMillis].
* @throws IllegalArgumentException if [minCharacterChunk] is greater than [maxCharacterChunk].
*/
@Composable
fun TypewriterTextEffect(
text: String,
minDelayInMillis: Long = 10,
maxDelayInMillis: Long = 50,
minCharacterChunk: Int = 1,
maxCharacterChunk: Int = 5,
onEffectCompleted: () -> Unit = {},
displayTextComposable: @Composable (displayedText: String) -> Unit
) {
// Ensure minDelayInMillis is less than or equal to maxDelayInMillis
require(minDelayInMillis <= maxDelayInMillis) {
"TypewriterTextEffect: Invalid delay range. minDelayInMillis ($minDelayInMillis) must be less than or equal to maxDelayInMillis ($maxDelayInMillis)."
}
// Ensure minCharacterChunk is less than or equal to maxCharacterChunk
require(minCharacterChunk <= maxCharacterChunk) {
"TypewriterTextEffect: Invalid character chunk range. minCharacterChunk ($minCharacterChunk) must be less than or equal to maxCharacterChunk ($maxCharacterChunk)."
}
// Initialize and remember the displayedText
var displayedText by remember { mutableStateOf("") }
// Call the displayTextComposable with the current displayedText value
displayTextComposable(displayedText)
// Launch the effect to update the displayedText value over time
LaunchedEffect(text) {
val textLength = text.length
var endIndex = 0
while (endIndex < textLength) {
endIndex = minOf(
endIndex + Random.nextInt(minCharacterChunk, maxCharacterChunk + 1),
textLength
)
displayedText = text.substring(startIndex = 0, endIndex = endIndex)
delay(Random.nextLong(minDelayInMillis, maxDelayInMillis))
}
onEffectCompleted()
}
}
/**
* An example composable that uses the TypewriterTextEffect function.
*/
@Composable
fun ExampleTypewriterTextEffect() {
// Use the TypewriterTextEffect composable with a Text composable to display the text with the typewriter effect
Box(
Modifier
.fillMaxSize()
.padding(16.dp)
) {
TypewriterTextEffect(text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") { displayedText ->
Text(
modifier = Modifier.fillMaxWidth(),
text = displayedText,
style = MaterialTheme.typography.h5
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment