在 Android Kotlin 中使文本一一出现(又名打字机效果)

Ton*_*eth 3 android kotlin

这可能是一个基本问题,或者我可能使我的项目远远超出了我的能力,但我确实可以在这方面使用帮助,这花费了我数小时的搜索和尝试其他人的代码。

我的活动包括使用 ViewPager2 的三个片段,我将它们称为片段 A、B 和 C。其中,片段 B 将加载另一个未指定数量的片段。我将其称为片段 X1、X2...可能是 X99 左右。这些片段是使用打字机效果的地方,所以我将文本动画功能放在片段 B 上,因为我认为最好在加载片段的位置而不是每个片段 Xn 都有它。

fun TextView.textDisplay(text: Int) {
    val targetstring: Int = text
    if(textanim) {
            for(i in 1..targetstring){
                println(targetstring.toString()[i])
                Thread.sleep(textanimspeed.toLong())
            } // Typewriter effect
    } else {
        println(targetstring)
    } // display texts at once
}
Run Code Online (Sandbox Code Playgroud)

片段 B 中还有一些值,我计划使用它们来设置文本的大小、动画速度以及是否动画。

var textsize:Byte = 10
var textanimspeed:Byte = 100
var textanim: Boolean = true
Run Code Online (Sandbox Code Playgroud)

然后尝试加载Fragment X1。

(activity as FragmentB).TextView1.textDisplay(R.string.stringX1)
Run Code Online (Sandbox Code Playgroud)

事实证明,这行代码无法访问,并且“textDisplay”是“未解析的引用”。

如果我删除 textDisplay(text: Int) 的接收器参数“TextView”并且执行代码 Android studio 不会说它未解决,但它仍然无法访问。最重要的是,我相信文本必须在 TextView 内进行动画处理。运行该应用程序不会向我显示任何文本。

我尝试的第二件事是复制打字机效果的 Java 代码并粘贴它,这样 Android studio 就会自动将其转换为 Kotlin。结果有一些红色,但我把它去掉了。我创建了一个新类“TypeWriterView.kt”,其代码如下:

class TypeWriterView: AppCompatTextView {
  private var mText: CharSequence? = null
  private var mIndex = 0
  private var mDelay: Long = 150 // in ms

  constructor(context: Context) : super(context)
  constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

  private val mHandler: Handler = Handler()
  private val characterAdder: Runnable = object : Runnable {
    override fun run() {
        text = mText!!.subSequence(0, mIndex++)
        if (mIndex <= mText!!.length) {
            mHandler.postDelayed(this, mDelay)
        }
    }
  }

  fun animateText(txt: CharSequence?) {
    mText = txt
    mIndex = 0
    text = ""
    mHandler.removeCallbacks(characterAdder)
    mHandler.postDelayed(characterAdder, mDelay)
  }

  fun setCharacterDelay(m: Long) {
    mDelay = m
  }
}
Run Code Online (Sandbox Code Playgroud)

并在 Fragment X1 中尝试过。

    Sc_X1_tv01.setText(R.string.stringX1)
    Sc_X1_tv01.setCharacterDelay(150)
    Sc_X1_tv01.animateText("${R.string.stringX1}")
Run Code Online (Sandbox Code Playgroud)

它没有红色,但仍然“无法访问”,并且在运行时不会向我显示任何文本。

我被困在这一点上并寻求帮助。感谢您的阅读,如有任何帮助,我们将不胜感激。

Ten*_*r04 5

使用协程可以非常简单地在单个函数中完成打字机效果,然后您可以将其用于任何 TextView,而无需创建任何属性。

fun TextView.typeWrite(lifecycleOwner: LifecycleOwner, text: String, intervalMs: Long) {
    this@typeWrite.text = ""
    lifecycleOwner.lifecycleScope.launch {
        repeat(text.length) {
            delay(intervalMs)
            this@typeWrite.text = text.take(it + 1)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

// In an Activity:
myTextView.typeWrite(this, "Hello, world!", 33L)

// In a Fragment:
myTextView.typeWrite(viewLifecycleOwner, "Hello, world!", 33L)

Run Code Online (Sandbox Code Playgroud)

至于您自己的代码,第一个策略将不起作用,因为您不能在 UI 线程上休眠。您的策略与上面我的类似,只是delay()在协程中不会休眠您启动它的线程,而是挂起协程。我不明白你的第二次尝试有什么问题,但它可能在你没有发布的代码中。不确定你所说的“无法访问”是什么意思。