在AndroidKotlin中使文本逐个显示(又名打字机效果)

njthzxwz  于 2023-08-07  发布在  Kotlin
关注(0)|答案(2)|浏览(207)

这可能是一个基本的问题,或者我可能使我的项目远远超出了我的能力,但我真的可以使用一个帮助对这一点,我花了几个小时的搜索和尝试别人的代码。
我的活动包括三个使用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
}

字符串
在片段B中也有一些值,我计划使用它们来设置文本的大小、动画速度以及是否将其动画化。

var textsize:Byte = 10
var textanimspeed:Byte = 100
var textanim: Boolean = true


然后试图加载片段X1。

(activity as FragmentB).TextView1.textDisplay(R.string.stringX1)


结果是这行代码是不可访问的,“textDisplay”是“unresolved reference”。
如果我删除textDisplay(文本:Int)和执行代码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
  }
}


并在片段X1中进行了尝试。

Sc_X1_tv01.setText(R.string.stringX1)
    Sc_X1_tv01.setCharacterDelay(150)
    Sc_X1_tv01.animateText("${R.string.stringX1}")


它没有红色,但仍然是“无法访问”,并没有显示我运行时的任何文本。
我被困在这一点上,寻求帮助。感谢阅读,任何帮助都将不胜感激。

uyto3xhc

uyto3xhc1#

一个打字机效果可以在一个函数中完成,非常简单,使用协程,然后你可以在任何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)
        }
    }
}

字符串
使用方法:

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

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


至于您自己的代码,第一个策略将不起作用,因为您不能在UI线程上休眠。您的策略与我上面的策略类似,不同之处在于协程中的delay()不会使启动它的线程休眠,而是挂起协程。我看不出你的第二次尝试有什么问题,但可能是你没有发布的代码。我不知道你说的“不可及”是什么意思。

nnt7mjpx

nnt7mjpx2#

如果有人还在找的话您可以不使用lifecycleOwner,而使用ValueAnimator来完成此操作。

fun TextView.animateCharacterByCharacter(text: String, delay: Long = 33L) {
    // Make sure the text is not empty
    if (text.isEmpty()) return

    // Initialize a value animator to iterate over characters
    val charAnimation = ValueAnimator.ofInt(0, text.length)

    charAnimation.apply {
        this.duration = delay * text.length.toLong()
        this.repeatCount = 0
        addUpdateListener {
            val charCount = it.animatedValue as Int
            val animatedText = text.substring(0, charCount)
            this@animateCharacterByCharacter.text = animatedText
        }
    }

    charAnimation.start()
}

字符串

相关问题