Kotlin:用循环重复动画 x 次
Kotlin: Repeating an animation x times with a loop
我正在用 Kotlin 为 Android 做一个学校项目,这是一个呼吸练习应用程序。
我想遍历一个二维数组,其中包含某个练习中的步骤和每个步骤的持续时间,并为每个步骤设置一个进度条动画,动画长度为当前步长(以秒为单位)。
二维数组的例子:
[
["inhale", "10"],
["exhale", "10"],
["inhale", "5"],
["hold", "10"],
["exhale", "5"],
etc..
]
我尝试了以下 Kotlin 代码:
var currentExerciseType: String = ""
var currentExerciseDuration: Long = 0
var i = 0
while (i < exerciseList.size) {
motivation_text.append(exerciseList[i][0] + " \n")
currentExerciseType = exerciseList[i][0]
currentExerciseDuration = exerciseList[i][1].toLong() * 1000
exercise_type.text = currentExerciseType
val animation = ObjectAnimator.ofInt(progressBar, "progress", 0, 100)
animation.duration = currentExerciseDuration
animation.interpolator = DecelerateInterpolator()
animation.start()
animation.doOnEnd {
i++
}
}
当此功能为 运行 时,会导致屏幕黑屏。
我也尝试用 for 循环遍历数组,但它似乎没有等待每个动画完成,只是在屏幕上显示最后一步,而第一个动画仍然是 运行.
知道如何解决这个问题吗?
提前致谢。
您可以使用递归函数,使用您的代码 while 将继续循环,因为您没有等待动画结束。尝试类似的东西:
private fun animate(i : Int){
//do your things
animation.doOnEnd {
if(i < exerciseList.size)
animate(i+1)
}
.
.
.
//where you need to start the animation
animate(0)
}
您的代码不起作用的原因是动画 运行 是异步的。调用 start()
后,动画将排队等待开始,但您当前的 while 循环代码会立即继续。在当前代码完全完成之前,您在循环中创建的动画将不会启动,因此主线程将被释放以启动这些动画。 doOnEnd
代码将不会 运行 直到将来某个时间动画完成时,所以 i++
永远不会被调用并且你的 while 循环 运行 永远不会释放主线程,这样你的许多重复动画甚至可以开始。
因此,要在 while 循环中设置动画,您需要为每个动画指定一个延迟,该延迟是所有先前动画持续时间的总和。但是要做到这一点并不是很简单。
一种更简单的设置方法是创建动画列表,然后使用 AnimatorSet 按顺序播放它们。像这样的东西(我没有测试它。):
val animations = exerciseList.map { exercise ->
val exerciseType: String = exercise[0]
ObjectAnimator.ofInt(progressBar, "progress", 0, 100).apply {
duration = exercise[1].toLong() * 1000
doOnStart {
motivation_text.append(exerciseType + " \n")
exercise_type.text = exerciseType
}
}
}
AnimatorSet().run {
playSequentially(animations)
start()
}
如果您不熟悉 map
函数,它会从源数组中创建一个新列表,或者通过 运行 在 lambda 中调用代码并返回值来迭代。所以在这种情况下,它创建了一个 ObjectAnimators 列表,对应于原始列表中的每个项目。
我正在用 Kotlin 为 Android 做一个学校项目,这是一个呼吸练习应用程序。 我想遍历一个二维数组,其中包含某个练习中的步骤和每个步骤的持续时间,并为每个步骤设置一个进度条动画,动画长度为当前步长(以秒为单位)。
二维数组的例子:
[
["inhale", "10"],
["exhale", "10"],
["inhale", "5"],
["hold", "10"],
["exhale", "5"],
etc..
]
我尝试了以下 Kotlin 代码:
var currentExerciseType: String = ""
var currentExerciseDuration: Long = 0
var i = 0
while (i < exerciseList.size) {
motivation_text.append(exerciseList[i][0] + " \n")
currentExerciseType = exerciseList[i][0]
currentExerciseDuration = exerciseList[i][1].toLong() * 1000
exercise_type.text = currentExerciseType
val animation = ObjectAnimator.ofInt(progressBar, "progress", 0, 100)
animation.duration = currentExerciseDuration
animation.interpolator = DecelerateInterpolator()
animation.start()
animation.doOnEnd {
i++
}
}
当此功能为 运行 时,会导致屏幕黑屏。 我也尝试用 for 循环遍历数组,但它似乎没有等待每个动画完成,只是在屏幕上显示最后一步,而第一个动画仍然是 运行.
知道如何解决这个问题吗? 提前致谢。
您可以使用递归函数,使用您的代码 while 将继续循环,因为您没有等待动画结束。尝试类似的东西:
private fun animate(i : Int){
//do your things
animation.doOnEnd {
if(i < exerciseList.size)
animate(i+1)
}
.
.
.
//where you need to start the animation
animate(0)
}
您的代码不起作用的原因是动画 运行 是异步的。调用 start()
后,动画将排队等待开始,但您当前的 while 循环代码会立即继续。在当前代码完全完成之前,您在循环中创建的动画将不会启动,因此主线程将被释放以启动这些动画。 doOnEnd
代码将不会 运行 直到将来某个时间动画完成时,所以 i++
永远不会被调用并且你的 while 循环 运行 永远不会释放主线程,这样你的许多重复动画甚至可以开始。
因此,要在 while 循环中设置动画,您需要为每个动画指定一个延迟,该延迟是所有先前动画持续时间的总和。但是要做到这一点并不是很简单。
一种更简单的设置方法是创建动画列表,然后使用 AnimatorSet 按顺序播放它们。像这样的东西(我没有测试它。):
val animations = exerciseList.map { exercise ->
val exerciseType: String = exercise[0]
ObjectAnimator.ofInt(progressBar, "progress", 0, 100).apply {
duration = exercise[1].toLong() * 1000
doOnStart {
motivation_text.append(exerciseType + " \n")
exercise_type.text = exerciseType
}
}
}
AnimatorSet().run {
playSequentially(animations)
start()
}
如果您不熟悉 map
函数,它会从源数组中创建一个新列表,或者通过 运行 在 lambda 中调用代码并返回值来迭代。所以在这种情况下,它创建了一个 ObjectAnimators 列表,对应于原始列表中的每个项目。