You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:21:41