Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fill a Path with linear gradient in an Android custom view

I have created an Android Custom View using Kotlin to draw a Star which will be used to create a custom RatingBar in future; So I extended the View class and override its draw() method to draw one Star considering this guide from Google: https://developer.android.com/training/custom-views/custom-drawing

After that, I tried to fill the star path with linear gradient to achieve the star filling effect following this Post: How to fill a Path in Android with a linear gradient?

class CustomStar constructor(context: Context, attr: AttributeSet) : View(context, attr) {

    private var paint: Paint = Paint(Paint.FILTER_BITMAP_FLAG)
    private var path: Path = Path()

    init {
        paint.shader = LinearGradient(0f, 0f, 0f, height.toFloat(), Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR)
    }

    override fun draw(canvas: Canvas?) {
        super.draw(canvas)

        // draw the star.
        val min = Math.min(width, height).toFloat()
        // top left
        path.moveTo(0f, min * 0.3819901313f)
        // top right
        path.lineTo(min, min * 0.3819901313f)
        // bottom left
        path.lineTo(min * 0.1910982479f, min)
        // top tip
        path.lineTo(min * 0.5f, 0f)
        // bottom right
        path.lineTo(min*0.8089799735f, min)
        // top left
        path.lineTo(0f, min * 0.3819901313f)

        path.close()
        canvas?.drawPath(path, paint)
    }
}

As you can see in init, The paint object's shader attribute is set to LinearGradient(0f, 0f, 0f, height.toFloat(), Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR) so I should expect the shape to be filled with the gradient.

But the problem is that I only get a solid filled star instead of the gradient, as showcased in the photo:

Solid Filled Star

Now the question is, why am I getting a solid color instead of gradient in the star?

Thank you for your attention.

like image 840
superus8r Avatar asked Dec 14 '22 16:12

superus8r


1 Answers

The view's height is unknown at this point:

init {
    paint.shader = LinearGradient(0f, 0f, 0f, height.toFloat(), Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR)
}

Instead override onSizeChanged and create the LinearGradient there:

override fun onSizeChanged(w: Int, h: Int, oldW: Int, oldH: Int) {
    paint.shader = LinearGradient(0f, 0f, 0f, h.toFloat(), Color.YELLOW, Color.WHITE, Shader.TileMode.MIRROR)
}
like image 84
eski Avatar answered Dec 17 '22 22:12

eski