
项目中,为了实现好看的效果UI娘们会,设计出各式各样的渐变色效果,真是UI大手一挥,开发跑断腿(可能是我菜).这不又开始了 ,四种颜色,还根据位置动态位置实现倾斜角度渐变,好多页面要用.
人家切好图了....
不想往码子里放太多的图,所以还是肝一下这个渐变色吧
go-->go-->go
Android渐变色功能的底层实现依赖于图形渲染引擎和着色器(Shader)机制,核心原理是通过颜色插值算法 和坐标映射在指定区域内平滑过渡多种颜色。具体实现分为两大技术路径:
渐变色实现分类
- Drawable资源系统(xml,
GradientDrawable
两种方式实现) - Shader(功能强大
推荐手写
)
1:Drawable资源系统(XML预定义+CPU解析)

通过XML定义静态渐变色,系统在运行时解析为GradientDrawable
对象,然后实现各种渐变色
核心:
实质上是 将xml
转为GradientDrawable
GradientDrawable是Drawable的子类所以可以直接设置给控件做背景
所以Drawable资源系统实现渐变色可分为两类 xml静态资源实现渐变色和GradientDrawable
对象实现渐变色
- xml静态资源实现渐变色
- GradientDrawable实现
注意:
1:XML 中最多只能设置3
种颜色(startColor
、centerColor
、endColor
) 2:角度限制:android:angle
必须是 45
的倍数,否则会自动取模(如设置 30° 实际会变为 30%45=30°)
1.1 xml静态资源实现渐变色
渐变色实现效果类型:
- 线性渐变(LinearGradient)
- 径向渐变(RadialGradient)
- 扫描渐变(SweepGradient)
1.1.1 线性渐变(LinearGradient)

属性说明
- 仅仅支持三种颜色
- angle 渐变方向:0=左到右,45斜角90=上到下,,135对斜角,180=右到左,270=下到上
- startColor 起始颜色
- centerColor 中间颜色
- endColor 结束颜色
- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果
View设置
ini
<View
android:layout_margin="10dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/gradient_linear"/>
资源 gradient_linear.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 仅仅支持三种颜色 -->
<!-- angle 渐变方向:0=左到右,45斜角90=上到下,,135对斜角,180=右到左,270=下到上 -->
<!-- startColor 起始颜色 -->
<!-- centerColor 中间颜色 -->
<!-- endColor 结束颜色 -->
<!-- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果-->
<gradient
android:angle="90"
android:startColor="#FF4081"
android:centerColor="@color/teal_200"
android:endColor="#3F51B5"
android:type="linear"
android:useLevel="false" />
</shape>
1.1.2 径向渐变(RadialGradient)

属性说明:
- 仅仅支持三种颜色
- gradientRadius 渐变半径(必须设置)
- centerX 中心点X坐标(0-1) -->
- centerY 中心点Y坐标
- startColor 起始颜色
- centerColor 中间颜色
- endColor 结束颜色
- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果
View设置
ini
<View
android:layout_margin="10dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/gradient_radial"/>
xml资源 gradient_radial.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 仅仅支持三种颜色 -->
<!-- startColor 起始颜色 -->
<!-- centerColor 中间颜色 -->
<!-- endColor 结束颜色 -->
<!-- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果-->
<!-- gradientRadius 渐变半径(必须设置) -->
<!-- centerX 中心点X坐标(0-1) -->
<!-- centerY 中心点Y坐标 -->
<gradient
android:type="radial"
android:endColor="#3F51B5"
android:centerColor="@color/teal_200"
android:startColor="#FF4081"
android:gradientRadius="70dp"
android:centerX="0.5"
android:centerY="0.5"
android:useLevel="false"
/>
</shape>
1.1.3 扫描渐变(LinearGradient)

属性说明:
- 仅仅支持三种颜色
- centerX 中心点X坐标(0-1) -->
- centerY 中心点Y坐标
- startColor 起始颜色
- centerColor 中间颜色
- endColor 结束颜色
- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果
View设置
ini
<View
android:layout_margin="10dp"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/gradient_sweep"/>
xml资源 gradient_sweep.xml
xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 仅仅支持三种颜色 -->
<!-- startColor 起始颜色 -->
<!-- centerColor 中间颜色 -->
<!-- endColor 结束颜色 -->
<!-- useLevel 必须为false true时渐 变色会根据 level 值(范围 0-10000)动态调整显示效果-->
<!-- gradientRadius 渐变半径(必须设置) -->
<!-- centerX 中心点X坐标(0-1) -->
<!-- centerY 中心点Y坐标 -->
<gradient
android:type="sweep"
android:endColor="#3F51B5"
android:centerColor="@color/teal_200"
android:startColor="#FF4081"
android:centerX="0.5"
android:centerY="0.5"
android:useLevel="false"
/>
</shape>
1.2 GradientDrawable 代码实现渐变

scss
val gradient = GradientDrawable(
GradientDrawable.Orientation.BOTTOM_TOP, // 渐变方向
colors// 颜色数组
)
binding.view1.setBackgroundDrawable(gradient)
var gradient2 = GradientDrawable()
gradient2.setGradientType(GradientDrawable.RADIAL_GRADIENT)
gradient2.setColors(colors) // 从中心到边缘的颜色
gradient2.setGradientRadius(dp2px(70f).toFloat()) // 渐变半径(必须设置)
gradient2.setGradientCenter(0.5f ,0.5f )// 中心点 X 坐标(0-1)
binding.view2.setBackgroundDrawable(gradient2)
val gradient3 = GradientDrawable()
gradient3.setGradientType(GradientDrawable.SWEEP_GRADIENT)
gradient3.setColors(colors) // 颜色需首尾闭合
gradient3.setGradientCenter(0.5f ,0.5f )// 中心点 X 坐标(0-1)
binding.view3.setBackgroundDrawable(gradient3)
2.Shader渲染引擎(基于GPU的实时计算)
Shader是Android图形系统(android.graphics
)的核心组件,负责定义像素填充规则。渐变色通过以下Shader子类实现:
- 多颜色
- 多位置
- 多角度

- LinearGradient(线性渐变)
- RadialGradient(径向渐变)
- SweepGradient(扫描渐变)
2.1 LinearGradient(线性渐变)
kotlin
/**
* 支持自定义线性渐变的View
*/
class LinearGradientView : View {
// 1. 代码创建时调用
constructor(context: Context?) : super(context)
// 2. XML布局加载时必须调用(关键!)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
// 3. 可选:支持主题样式时添加
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
// 使用更合适的命名和初始化方式
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
// 使用val声明不可变数组,初始化颜色值
private val colors = intArrayOf(
Color.parseColor("#FF4081"),
Color.parseColor("#FF03DAC5"),
Color.parseColor("#3F51B5")
)
// 确保gradientLocations长度与colors一致
private val gradientLocations = floatArrayOf(0f, 0.46f, 1f)
// 缓存渐变对象,避免每次onDraw重新创建
private var linearGradient: Shader? = null
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
// 当View尺寸变化时创建渐变对象
if (w > 0 && h > 0) {
linearGradient = LinearGradient(
0f, 0f,
w.toFloat(), h.toFloat(),
colors,
gradientLocations,
Shader.TileMode.CLAMP
)
paint.shader = linearGradient
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 绘制矩形区域,应用渐变
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
}
}
2.1 RadialGradient(径向渐变)
kotlin
package com.wkq.tools.ui.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RadialGradient
import android.graphics.Shader
import android.util.AttributeSet
import android.view.View
import kotlin.math.min
/**
* 支持径向渐变的自定义View
*/
class RadialGradientView : View {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
// 使用不可变数组并修正颜色位置定义
private val colors = intArrayOf(
Color.parseColor("#FF4081"),
Color.parseColor("#FF03DAC5"),
Color.parseColor("#3F51B5")
)
// 确保颜色位置数组长度与颜色数组一致
private val gradientLocations = floatArrayOf(0f, 0.46f, 1f)
// 缓存渐变对象避免重复创建
private var radialGradient: Shader? = null
// 记录当前尺寸
private var currentWidth = 0
private var currentHeight = 0
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
context, attrs, defStyleAttr
)
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
// 保存当前尺寸
currentWidth = w
currentHeight = h
// 尺寸变化时重新创建渐变
createRadialGradient()
}
private fun createRadialGradient() {
if (currentWidth <= 0 || currentHeight <= 0) return
val centerX = currentWidth / 2f
val centerY = currentHeight / 2f
val radius = min(centerX, centerY)
radialGradient = RadialGradient(
centerX, centerY,
radius,
colors,
gradientLocations,
Shader.TileMode.CLAMP
)
paint.shader = radialGradient
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (currentWidth <= 0 || currentHeight <= 0) return
val centerX = currentWidth / 2f
val centerY = currentHeight / 2f
val radius = min(centerX, centerY)
// 绘制圆形区域应用径向渐变
canvas.drawCircle(centerX, centerY, radius, paint)
}
}
2.3 SweepGradient(扫描渐变)
kotlin
package com.wkq.tools.ui.view
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.SweepGradient
import android.util.AttributeSet
import android.view.View
import kotlin.math.min
/**
* 支持扫描渐变的自定义View
*/
class SweepGradientView: View{
// 1. 代码创建时调用
constructor(context: Context?) : super(context)
// 2. XML布局加载时必须调用(关键!)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
// 3. 可选:支持主题样式时添加
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
// 使用不可变数组存储颜色
private val colors = intArrayOf(
Color.parseColor("#FF4081"),
Color.parseColor("#FF03DAC5"),
Color.parseColor("#3F51B5")
)
// 确保颜色位置数组长度与颜色数组一致
private val gradientLocations = floatArrayOf(0f, 0.46f, 1f)
// 缓存渐变对象,避免每次onDraw重新创建
private var sweepGradient: SweepGradient? = null
// 记录当前尺寸
private var currentWidth = 0
private var currentHeight = 0
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
currentWidth = w
currentHeight = h
createSweepGradient()
}
private fun createSweepGradient() {
if (currentWidth <= 0 || currentHeight <= 0) return
val centerX = currentWidth / 2f
val centerY = currentHeight / 2f
sweepGradient = SweepGradient(
centerX, centerY,
colors,
gradientLocations
)
paint.shader = sweepGradient
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (currentWidth <= 0 || currentHeight <= 0) return
val centerX = currentWidth / 2f
val centerY = currentHeight / 2f
val radius = min(centerX, centerY)
// 绘制圆形区域应用扫描渐变
canvas.drawCircle(centerX, centerY, radius, paint)
}
}
总结
Drawable资源系统 将XML静态资源转化为 GradientDrawable
或者代码创建,可以直接设置给View控件作为背景
Shader方式实现渐变是给画笔设置Shader用于绘制的时候,适合在自定义View的时候.