Если вы посмотрите на javado c для imageView.setImageResource
, вы увидите, что он вызывает сбой задержки, поскольку загружает изображение в поток пользовательского интерфейса.
Я думаю, вы можете исправить это путем предварительной загрузки вашего следующего drawable в фоновом режиме. Я не пробовал этого, потому что я не работаю с анимационными рисованными объектами, поэтому заранее извиняюсь, если это не излечит икоту.
Сопрограммы упростят настройку и поддержание порядка. Вы можете начать с создания функции, которая устраняет необходимость использования вложенных обратных вызовов Animator:
suspend fun Animator.runToCompletion(): Unit = suspendCoroutine { cont ->
doOnEnd { cont.resume(Unit) }
start()
}
Затем, когда вы запускаете анимацию, вы можете начать загрузку следующего рисованного в фоновом режиме, и, надеюсь, он будет готов время, когда вам нужно показать это:
val cxt = requireContext() // one source of failure if context is null
lifecycleScope.launch {
// Start loading the second animation in a background thread
val spellStopAnimationJob: Deferred<AnimationDrawable> = async(Dispatchers.Default) {
cxt.getDrawable(ctx.resources.getIdentifier(
"${spellCasted}stop_anim",
"drawable", ctx.packageName
) as AnimationDrawable
}
view.setImageResource(
resources.getIdentifier(
"${spellCasted}_anim",
"drawable", cxt.packageName
)
)
val x1 = startXposition
val x2 = firstXdestination
val initialAnimation = view.drawable as AnimationDrawable
.apply { start() }
view.visibility = View.VISIBLE
ObjectAnimator.ofFloat(
view,
"translationX",
x1.toFloat(),
x2.toFloat()
).apply {
duration = 900L
interpolator = LinearInterpolator()
}.runToCompletion()
if (hasPost(splitSpell)) { //hasPost(..) check is there additional image to translate from x2 to x2 + 20
initialAnimation.stop()
// Wait for the animation to be loaded (hopefully it's already done so no hiccup)
val stopAnimation = spellStopAnimationJob.await()
.apply { start() }
view.setImageDrawable(stopAnimation)
ObjectAnimator.ofFloat(
view, "translationX",
x2.toFloat(),
x2.toFloat() + 20f
).apply {
duration = 1200
interpolator = LinearInterpolator()
}.runToCompletion()
}
setDefault(view, x1, isEnemy)//returns view to startPos
}
Кстати, эта строка x2.toFloat() + 20f
будет мешать вам при запуске этого на разных устройствах, так как вы жестко кодируете смещение в пикселях вместо DIP-блоков. Вы должны указать число в единицах DIP и умножить на resources.displayMetrics.density
, чтобы преобразовать его в пиксельные единицы.