Переход GradientDrawable - PullRequest
       18

Переход GradientDrawable

0 голосов
/ 14 мая 2019

У меня есть функция, которая создает градиент на фоне моего MainActivity.Градиент создается программно как GradientDrawable.Определенные взаимодействия в приложении меняют цвет градиента.

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

fun createGradient() {
    gd.shape = GradientDrawable.RECTANGLE
    mainActivityID.background = gd
    gd.gradientType = GradientDrawable.LINEAR_GRADIENT
    gd.orientation = (GradientDrawable.Orientation.BL_TR)
}

На основе взаимодействий в приложении я использую оператор when, чтобы изменить цвета GradientDrawable

fun changeGradient(){

    //val td = gd as TransitionDrawable
    //td.isCrossFadeEnabled = true
    //td.startTransition(1500)

    when(calories){
        in 0..50 -> gd.colors = intArrayOf(
            ContextCompat.getColor(this, R.color.dBlue),
            ContextCompat.getColor(this, R.color.lBlue)
        )
        in 51..100 -> gd.colors = intArrayOf(
            ContextCompat.getColor(this, R.color.dRed),
            ContextCompat.getColor(this, R.color.lRed)
        )
        // etc...
    }
}

Я пытался привести GradientDrawable как TransitionDrawable (как видно из приведенного выше прокомментированного кода), но он завершается с:

java.lang.ClassCastException: android.graphics.drawable.GradientDrawable не может быть приведенto android.graphics.drawable.TransitionDrawable

Как добавить 1500-миллисекундный переход между изменениями цвета GradientDrawable?

Сбой выполнения с java.lang.NegativeArraySizeException: -16777216

when(calories){
    in 0..50 -> animateGradient(gd, IntArray(Color.BLACK), IntArray(Color.CYAN))
    in 51..100 -> animateGradient(gd, IntArray(Color.RED), IntArray(Color.BLUE))
    in 101..150 -> animateGradient(gd, IntArray(Color.GREEN), IntArray(Color.YELLOW))
    // etc... about 15 more statements.
}

1 Ответ

1 голос
/ 15 мая 2019

Я не думаю, что в Gradient Drawable есть встроенные методы перехода, но вы можете запустить собственный аниматор значений для выполнения цветового перехода.

var anim : Animator? = null

fun animateGradient(gd: GradientDrawable, from : IntArray, to: IntArray){
    require(from.size == to.size)
    anim?.cancel()
    val arraySize = from.size
    val props = Array<PropertyValuesHolder>(arraySize){
        PropertyValuesHolder.ofObject(it.toString(), ArgbEvaluator(), from[it], to[it])
    }
    val anim = ValueAnimator.ofPropertyValuesHolder(*props)
    anim.addUpdateListener {
        gd.colors = IntArray(arraySize){i ->
            it.getAnimatedValue(i.toString()) as Int
        }
    }
    anim.duration = 1500
    anim.start()
    this.anim = anim
}

Редактировать : модифицированный метод, так чтокоторый отслеживает текущий цвет, уменьшенное количество аргументов.

var anim : Animator? = null
// variable that tracks current color - must be initialized with default gradient colors
var currentGradient = intArrayOf(
        ContextCompat.getColor(this, R.color.dBlue),
        ContextCompat.getColor(this, R.color.lBlue)
    )

fun animateGradient(targetColors: IntArray){
    val from = currentGradient
    require(from.size == targetColors.size)
    anim?.cancel()
    val arraySize = from.size
    val props = Array<PropertyValuesHolder>(arraySize){
        PropertyValuesHolder.ofObject(it.toString(), ArgbEvaluator(), from[it], targetColors[it])
    }
    val anim = ValueAnimator.ofPropertyValuesHolder(*props)
    anim.addUpdateListener {valueAnim ->
        IntArray(arraySize){i ->
            valueAnim.getAnimatedValue(i.toString()) as Int
        }.let{
            currentGradient = it
            gd.colors = it
        }
    }
    anim.duration = 1500
    anim.start()
    this.anim = anim
}

Звонок на сайт:

when(calories){
    in 0..50 -> animateGradient(intArrayOf(
        ContextCompat.getColor(this, R.color.dBlue),
        ContextCompat.getColor(this, R.color.lBlue)
    ))
    in 51..100 -> animateGradient(intArrayOf(
        ContextCompat.getColor(this, R.color.dRed),
        ContextCompat.getColor(this, R.color.lRed)
    ))
    // etc...
}
...