Анимация в представлении с помощью ConstraintLayout.LayoutParams заканчивается мгновенно

#android #kotlin #android-animation

#Android #kotlin #android-анимация

Вопрос:

В настоящее время я пытаюсь изменить matchConstraintPercentWidth значение представления с 2 на 0, используя Animation() при запуске моей деятельности (в методе onWindowFocusChanged() , чтобы убедиться, что все представления были нарисованы правильно). Проблема в том, что анимация заканчивается мгновенно (и у этого представления теперь есть новые параметры — похоже, что продолжительность анимации равна 0 мс), независимо от продолжительности, которую я установил… Вот мой код (на Kotlin) :

 override fun onWindowFocusChanged(hasFocus: Boolean) {
        if (hasFocus) {
            val gradient = findViewById<ImageView>(R.id.black_gradient)
            val animation = object : Animation() {
                override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
                    val params = gradient.layoutParams as ConstraintLayout.LayoutParams
                    params.matchConstraintPercentWidth = 0f
                    gradient.layoutParams = params
                }
            }
            animation.duration = 2000L // in ms
            gradient.startAnimation(animation) //also tried animation.start() without effect
            //animation.hasStarted() is always false here
        }
    }
  

Любая помощь приветствуется 😉

Ответ №1:

Этот applyTransformation метод предназначен для вычисления текущего состояния анимации на основе interpolatedTime (что находится между 0.0 и 1.0 ). Вы просто устанавливаете значение ограничения равным 0, поэтому на самом деле оно не изменяет значение с течением времени и ничего не анимирует.

Честно говоря, вы, вероятно, не захотите ничего из этого трогать, если сможете, в Android есть несколько вспомогательных классов, которые абстрагируют многие детали, так что вы можете просто анимировать вещь.ValueAnimator, вероятно, хороший крик, вы могли бы просто сделать

 ValueAnimator.ofFloat(0f, 100f).apply {
    addUpdateListener { anim ->
        val params = (gradient.layoutParams as ConstraintLayout.LayoutParams)
        params.matchConstraintPercentWidth = anim.animatedValue as Float
    }
    duration = 1000
    start()
}
  

и это должно быть эквивалентно тому, что вы делаете. ObjectAnimator По этой ссылке тоже есть ссылка, но для этого требуется метод установки, а для этого параметра макета его нет (у ConstraintProperties есть некоторые, но не для этого, насколько я вижу)

Комментарии:

1. Спасибо! Это работает (но нам абсолютно необходимо обновить и применить процентную ширину, используя gradient.layoutParams = params в конце addUpdateListener() ^^

2. Ах, хорошо, да, я просто обрезал его, но я действительно ничего не знаю об анимации параметров макета! Кроме того, если вы еще не видели MotionLayout , об этом может быть полезно знать, посмотрите, соответствует ли это тому, что вы делаете (это также, по-видимому, новая мода) developer.android.com/training/constraint-layout/motionlayout

Ответ №2:

Для меня код выглядит нормально, попробуйте удалить условие hasFocus , потому что могут быть некоторые представления, которые могут попасть в фокус до того, как эта конкретная вещь, которую вы должны сделать для диагностики, это

  1. попробуйте войти hasFocus , если он не получает фокус, затем измените код, как показано ниже, также просто совет, который вы всегда должны инициализировать представления вне обратных вызовов.

      override fun onWindowFocusChanged(hasFocus: Boolean) {
                 val gradient = findViewById<ImageView>(R.id.black_gradient)
                 val animation = object : Animation() {
                     override fun applyTransformation(interpolatedTime: Float, t: Transformation?) {
                         val params = gradient.layoutParams as ConstraintLayout.LayoutParams
                         params.matchConstraintPercentWidth = 0f
                         gradient.layoutParams = params
                     }
                 }
                 animation.duration = 2000L // in ms
                 gradient.startAnimation(animation) //also tried animation.start() without effect
                 //animation.hasStarted() is always false here
         }