Untitled
unknown
kotlin
5 years ago
3.1 kB
6
Indexable
@OptIn(ExperimentalComposeApi::class)
@Composable
fun Android11PinAnimation(modifier: Modifier = Modifier, text: String) {
val textFlow = parameterToFlow(text)
Row(
modifier.fillMaxWidth().height(60.dp),
verticalAlignment = Alignment.Bottom,
horizontalArrangement = Arrangement.Center,
) {
text.forEachIndexed { index, symbol ->
key(index, symbol) {
val textSize = animatedFloat(0f)
val bulletSize = animatedFloat(0f)
var pinToCenter by remember { mutableStateOf(false) }
launchInComposition {
val spring = SpringSpec<Float>(stiffness = Spring.StiffnessLow)
textSize.animateTo(1f, spring)
textFlow.waitUntil { text -> text.lastIndex != index }
delay(600)
pinToCenter = true
textSize.animateTo(0f, spring)
delay(100)
bulletSize.animateTo(1f)
}
var maxWidth by remember { mutableStateOf(0) }
val maxWidthDp = with(DensityAmbient.current) { maxWidth.toFloat() / density }
Box(
Modifier
.height(54.dp) // 40.sp
.onSizeChanged {
maxWidth = maxOf(maxWidth, it.width)
}
) {
Spacer(Modifier.width(maxWidthDp.dp))
Text(
symbol.toString(),
Modifier.align(if (pinToCenter) Alignment.Center else Alignment.BottomCenter),
fontSize = 40.sp * textSize.value,
)
Text(
"•",
Modifier.align(Alignment.Center),
fontSize = 40.sp * bulletSize.value,
)
}
}
}
}
}
@Composable
private fun <T> parameterToFlow(parameter: T): Flow<T> {
return remember { MutableStateFlow(parameter) }.also { it.value = parameter }
}
private suspend fun <T> Flow<T>.waitUntil(condition: (T) -> Boolean) {
takeWhile { !condition(it) }.collect { }
}
@Composable
@Preview
private fun Android11PinAnimationPreview() {
Providers(IndicationAmbient provides NoIndication) {
var text by remember { mutableStateOf("") }
Android11PinAnimation(
modifier = Modifier
.background(Color.Blue.copy(alpha = 0.1f))
.clickable {
text += (text.length % 10).toString()
if (text.length > 15) text = text.substring(15)
},
text = text
)
}
}
private val NoIndication: @Composable () -> Indication = {
object : Indication {
override fun createInstance(): IndicationInstance = object : IndicationInstance {
override fun ContentDrawScope.drawIndication(interactionState: InteractionState) {
drawContent()
}
}
}
}Editor is loading...