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

Android自定义View中星星路径线性渐变显示为纯色的原因

问题原因分析

你遇到的这个问题根源很明确——在init代码块中获取height时,View还没完成测量布局流程,此时height的数值是0。

当你创建LinearGradient(0f, 0f, 0f, height.toFloat(), ...)时,渐变的起始和结束Y坐标都是0,相当于把渐变压缩成了一个点,最终自然只能显示单一纯色(这里是渐变的起始色YELLOW)。

解决方案

要解决这个问题,你需要在View的尺寸确定之后再创建并设置LinearGradient。Android提供了onSizeChanged()方法,这个方法会在View大小发生变化(包括第一次确定尺寸)时被调用,完美适配这种依赖View尺寸的初始化逻辑。

修改后的代码如下:

class CustomStar constructor(context: Context, attr: AttributeSet) : View(context, attr) {
    private var paint: Paint = Paint(Paint.FILTER_BITMAP_FLAG)
    private var path: Path = Path()

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        // 此时View的实际高度h已经确定,用它来创建渐变
        paint.shader = LinearGradient(0f, 0f, 0f, h.toFloat(), Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR)
    }

    override fun draw(canvas: Canvas?) {
        super.draw(canvas)
        val min = Math.min(width, height).toFloat()
        path.reset() // 每次绘制前重置路径,避免重复累加路径点影响性能
        // 绘制星星路径
        path.moveTo(0f, min * 0.3819901313f)
        path.lineTo(min, min * 0.3819901313f)
        path.lineTo(min * 0.1910982479f, min)
        path.lineTo(min * 0.5f, 0f)
        path.lineTo(min*0.8089799735f, min)
        path.lineTo(0f, min * 0.3819901313f)
        path.close()
        canvas?.drawPath(path, paint)
    }
}
额外优化提示
  • 我在代码里添加了path.reset(),因为如果每次绘制不重置路径,会重复添加相同的路径点,导致路径结构越来越冗余,影响绘制效率。
  • 如果你后续要实现RatingBar的部分填充效果,可以考虑用ClipPath裁剪路径,或者动态调整渐变的范围来实现,这是个不错的扩展方向。

内容的提问来源于stack exchange,提问作者superus8r

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:57:15