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
相关产品推荐
相关产品推荐

