Implementing a Color Gradient Animation in Android with GradientDrawable and PropertyAnimator
This article demonstrates how to create a smooth color‑gradient animation for an Android view by dynamically configuring a GradientDrawable and driving the transition with a Kotlin PropertyAnimator, including code examples and step‑by‑step explanations.
1. Introduction
The article introduces a visual effect where a control’s background color gradually changes from one color to another after a click, aiming for a smooth transition without using custom views.
2. Scenario Analysis
It discusses the need for a gradual color change using gradients (linear, radial, sweep) and decides to use a linear gradient for the demonstration.
3. Implementation
(1) Gradient Implementation
Instead of static XML, the gradient is created programmatically with GradientDrawable . An initial demo uses two colors (purple and pink) and sets the drawable as the background of a TextView .
private fun setBg(){
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
drawable.colors = colors
tvTest?.background = drawable
}Attempts to animate the gradient using the drawable’s level property reveal limitations, prompting a switch to the newer setColors(colors, offsets) method available from Android Q.
(2) Color Transition Process
A ValueAnimator drives a float variable x from 0 to 1.1, which is used as offsets for the gradient, creating a smooth transition.
private fun setBg() {
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val offsets = floatArrayOf(x - 0.1f, x)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
drawable.setColors(colors, offsets)
}
tvTest?.background = drawable
}
private var mValueAnimator1: ValueAnimator? = null
fun startToStopChange() {
if (mValueAnimator1 == null) {
mValueAnimator1 = ValueAnimator.ofFloat(0f, 1.1f)
mValueAnimator1?.addUpdateListener {
x = it.animatedValue as Float
setBg()
}
}
mValueAnimator1?.setDuration(2000)?.start()
}The full activity code ties everything together, initializing the view, setting the initial background, and starting the animation on click.
var tvTest: TextView? = null
var x = 0f
private var mValueAnimator1: ValueAnimator? = null
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.test_main)
tvTest = findViewById(R.id.tv_test)
setBg()
tvTest?.setOnClickListener { startToStopChange() }
}
// setBg() and startToStopChange() implementations as shown above4. Summary
The effect is achieved in two steps: first, create a linear GradientDrawable with two colors; second, animate the gradient by updating its offsets via a ValueAnimator . The article emphasizes that complex UI effects are built from simple, well‑understood fundamentals.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.