我有一个函数可以在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无法转换为 android.graphics.drawable.TransitionDrawable
如何在GradientDrawable颜色更改之间添加1500毫秒的过渡?
进度崩溃,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.
}
答案 0 :(得分:1)
我认为渐变可绘制函数没有内置的过渡方法,但是您可以运行自己的值动画器来执行颜色过渡。
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...
}