#android #kotlin #animation
#Android #котлин #Анимация
Вопрос:
Я пытаюсь создать вибрирующую анимацию для просмотра изображения в Kotlin.
Вот код, с которого я начинаю:
var randomX = Random.nextInt(-100, 100).toFloat()
var moveX = ObjectAnimator.ofFloat(imageView, View.TRANSLATION_X, randomX).apply {
duration = 100
repeatCount = ObjectAnimator.INFINITE
addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator?) {}
override fun onAnimationEnd(animation: Animator?) {}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationRepeat(animation: Animator?) {
randomX = Random.nextInt(-100, 100).toFloat()
}
})
}
var randomY = Random.nextInt(-100, 100).toFloat()
var moveY = ObjectAnimator.ofFloat(imageView, View.TRANSLATION_Y, randomY).apply {
duration = 100
repeatCount = ObjectAnimator.INFINITE
addListener(object : Animator.AnimatorListener {
override fun onAnimationStart(animation: Animator?) {}
override fun onAnimationEnd(animation: Animator?) {}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationRepeat(animation: Animator?) {
randomY = Random.nextInt(-100, 100).toFloat()
}
})
}
var move = AnimatorSet()
move.playTogether(moveX, moveY)
move.start()
С чем у меня возникают проблемы, так это с изменением случайных значений и последующим обновлением анимации новыми случайными значениями при каждом повторении. Он всегда использует только начальные значения.
Ответ №1:
Ваши слушатели просто меняют эти var
значения, когда анимация повторяется, анимации уже определены с исходными значениями, поэтому при цикле ничего не меняется — он просто делает то же самое снова.
Вы можете получить желаемый эффект, в основном определяя новую анимацию каждый раз — вот способ с ViewPropertyAnimator
подходом:
fun randomPosition() = Random.nextInt(-100, 100).toFloat()
fun vibrate() {
imageView.animate()
.translationX(randomPosition())
.translationY(randomPosition())
.setDuration(100)
.withEndAction(::vibrate)
.start()
}
по сути, он выполняет то же самое, затем у него есть «конечное действие», которое просто снова вызывает функцию. Поскольку он каждый раз создает новую анимацию, он захватывает новую пару случайных значений.
Вы также можете контролировать количество повторений, если хотите!
fun vibrate(count: Int = 10) {
if (count < 1) return
imageView.animate()
.translationX(randomPosition())
.translationY(randomPosition())
.setDuration(100)
.withEndAction{ vibrate(count-1) }
.start()
}
Это просто уменьшает количество оставшихся вибраций, пока вы не достигнете нуля и анимация не прекратится. Я использовал значение параметра по умолчанию, чтобы вы могли определить там стандартное количество вибраций и просто звонить vibrate()
из любого места, которое его использует.
(Также это не рекурсивно, потому что на самом деле это не вызов функции изнутри самой себя — она делает это на более позднем этапе изнутри объекта функции, переданного аниматору. На случай, если вас это беспокоило!)