Android自定义Drawable的LinearGradient渐变背景显示纯色问题
问题根因
渐变失效显示纯色是两个代码逻辑错误导致的:
LinearGradient初始化时机错误:你在类成员声明位置创建渐变实例时,textWidth还未完成赋值,依赖textWidth计算的intrinsicWidth此时返回默认零值,相当于渐变的起止x坐标差极小,没有足够的横向拉伸距离,最终只会渲染单个色值的纯色。- Paint属性冲突:你给paint设置shader后又赋值了纯白色
paint.color = -0x1,部分Android系统版本上,Paint同时设置color和shader时,会优先使用color值做纯色填充,直接覆盖shader效果。
修复后代码
class TestDrawable(textSize: Int = 16) : Drawable() { private val rect = RectF() private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG) private val textWidth: Int private val text: String private lateinit var backgroundGradient: LinearGradient override fun draw(canvas: Canvas) { rect.set(bounds) canvas.drawRoundRect( rect, AndroidUtilities.dp(2f).toFloat(), AndroidUtilities.dp(2f).toFloat(), paint ) canvas.drawText( text, rect.left + AndroidUtilities.dp(5f), rect.top + AndroidUtilities.dp(12f), textPaint ) } override fun onBoundsChange(bounds: Rect) { super.onBoundsChange(bounds) // 绘制边界变化时同步更新渐变尺寸,适配实际宽高 backgroundGradient = LinearGradient( 0f, 0f, bounds.width().toFloat(), 0f, intArrayOf(-0xb73320, -0xafa523, -0x41bf40, -0x457d5), floatArrayOf(0.06f, 0.34f, 0.73f, 1f), Shader.TileMode.CLAMP ) paint.shader = backgroundGradient } override fun getIntrinsicWidth(): Int { return textWidth + AndroidUtilities.dp((5 * 2).toFloat()) } override fun getIntrinsicHeight(): Int { return AndroidUtilities.dp(16f) } init { textPaint.textSize = AndroidUtilities.dp(textSize.toFloat()).toFloat() textPaint.typeface = AndroidUtilities.getTypeface("fonts/rmedium.ttf") textPaint.color = -0x1000000 paint.style = Paint.Style.FILL // 删除paint.color = -0x1 避免纯色覆盖渐变 text = "plus".uppercase() textWidth = ceil(textPaint.measureText(text).toDouble()).toInt() // 等textWidth计算完成后再初始化渐变,保证尺寸参数正确 backgroundGradient = LinearGradient( 0f, 0f, intrinsicWidth.toFloat(), 0f, intArrayOf(-0xb73320, -0xafa523, -0x41bf40, -0x457d5), floatArrayOf(0.06f, 0.34f, 0.73f, 1f), Shader.TileMode.CLAMP ) paint.shader = backgroundGradient backgroundGradient.setLocalMatrix(Matrix()) } }
修改说明
- 调整渐变初始化顺序:将
LinearGradient的创建逻辑移到init块中textWidth赋值完成之后,确保创建渐变时能拿到正确的宽度参数 - 移除Paint的纯色设置:删除
paint.color = -0x1代码,避免纯色值覆盖shader的渐变绘制效果 - 新增
onBoundsChange回调处理:当Drawable实际绘制区域和固有尺寸不一致时,自动更新渐变的终点坐标,保证渐变始终完整铺满整个绘制区域,不会出现拉伸错位或截断问题
内容的提问来源于stack exchange,提问作者Drics
相关产品推荐
相关产品推荐

