To Dear 兮尘同学-Compose实现简单的打字机效果

1,351 阅读3分钟

前言

上篇文章 嘿嘿。又少了一个不用Compose的理由~官方支持跑马灯效果了! - 掘金 (juejin.cn),有位jy留言说想看看用Compose实现一个打字机的效果,我也用一个承诺换来了他的关注。正好我五一前离职了,经过小长假的调整后,今天正式开始交作业。

打字机效果

所谓打字机效果其实大致是由两个效果组成而来。逐字输出+底部横向下划线或者同字高的竖向划线光标

逐字输出

这个效果用我们利用Compose智能重组的特点来实现非常简单。

@Composable
fun Typewriter(
    fixedText: String,//默认显示的文字
    animatedText: String,//需要打字机效果的文字
) {
    //组合项内管理需要打字机效果的文字状态
    var _animatedText by remember { mutableStateOf("") }
    //申明最终需要在Text组合项显示的文字变量
    val textToDisplay = "$fixedText$_animatedText"
    
    LaunchedEffect(key1 = animatedText) {
        animatedText.forEachIndexed { charIndex, _ ->
            //遍历中赋值组合项管理的文字状态(延迟200毫秒后逐个新增字符后重新赋值)
            _animatedText = animatedText.substring(startIndex = 0, endIndex = charIndex + 1)
            delay(200)
        }


    }
    //_animatedText改变,textToDisplay跟着改变,textToDisplay改变后,作为Text组合项的参数,导致Text组合项触发重组。
    Text(
        text = textToDisplay,
        style = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 40.sp,
            letterSpacing = -(1.6).sp,
            lineHeight = 52.sp,
            color = Color.White,
        ),

    )

}


val animatePartsList = remember {
    "山不在高,有仙则名.水不在深,有龙则灵."

}

Typewriter(
    "小时候叔叔对我说:", animatePartsList,
)


我们来看看效果

通过Compose的重组特性,我们可以非常简单的实现这个逐字显示的动画!

光标

鲁迅说过,没有光标的打字机效果是没有灵魂的!实现光标前,先整理一下思路。

  1. 需要指定两种样式(底部下划线样式,右侧竖向光标样式)

  2. 光标在开始的时候顶头,一旦有字打印出来后需要在最后一个显示的字的右侧显示,所有字打印完毕需要隐藏光标。

  • 赖人方式
@Composable
fun Typewriter(
    fixedText: String,
    animatedText: String,
    orientation: Orientation=Orientation.Horizontal
) {
    var _animatedText by remember { mutableStateOf("") }
    val textToDisplay = "$fixedText$_animatedText"

    LaunchedEffect(key1 = animatedText) {
        animatedText.forEachIndexed { charIndex, _ ->
            _animatedText = animatedText.substring(startIndex = 0, endIndex = charIndex + 1)
            delay(200)
            //直接通过拼接方式在200毫秒内改变显示字符串的内容
            if (charIndex+1<animatedText.length){
                _animatedText += when (orientation) {
                    Orientation.Vertical -> "|"
                    Orientation.Horizontal -> "_"
                }
                delay(100)
            }

        }


    }

    Text(
        text = textToDisplay,
        style = TextStyle(
            fontWeight = FontWeight.SemiBold,
            fontSize = 40.sp,
            letterSpacing = -(1.6).sp,
            lineHeight = 52.sp,
            color = Color.White,
        ),
    )

}


val animatePartsList = remember {
    "山不在高,有仙则名.水不在深,有龙则灵."

}

Typewriter(
    "小时候叔叔对我说:", animatePartsList,Orientation.Vertical
)

加上光标效果后,逼格顿时提高几个档次!
横向 竖向

  • 自定义绘制
    上面的赖人的方式有取巧的嫌疑哈!不过够快够野。但是如果我们要实现更高定制的效果那就需要涉及到自定义绘制的知识了。所以我觉得正好可以利用这个效果来和大家一起初探一下Compose的自定义绘制的相关内容。感觉内容会比较多,所以会另开一篇再来接着这篇讲。

小结

首先感谢兮尘引出的这篇文章,没有你的留言。我也不会想到实现这个打字机效果,也不会有今天这篇文章。最关键的是,在实现的过程中确实对Compose的便捷和强大有了新的认识。期待往后的日子能跟更多的xdm一起碰撞火花,共同进步!