Search code examples
androidlinear-gradientshsv

Lineargradient is drawn offset from specified positon


I made a hue gradient with a Lineargradient with this code: (I know it could have been made simpler with Color.parseColor but it has to be this way for what I intend to do. I cannot use a drawable either.)

colors = new int[]{ Color.HSVToColor(new float[]{0, 1, 1}),
                    Color.HSVToColor(new float[]{60, 1, 1}), 
                    Color.HSVToColor(new float[]{120, 1, 1}), 
                    Color.HSVToColor(new float[]{180, 1, 1}),
                    Color.HSVToColor(new float[]{240, 1, 1}), 
                    Color.HSVToColor(new float[]{300, 1, 1}), 
                    Color.HSVToColor(new float[]{360, 1, 1}) };
Shader shader = new LinearGradient(0, 0, width, 0, colors, null, Shader.TileMode.CLAMP);
paint.setShader(shader);

Which produces this result with slightly offsetted colors, green area is too small and blue area is too large compared with the expected result.

comparison

I checked everything. I tried to use new float[]{0f, 1/6f, 2/6f, 3/6f, 4/6f, 5/6f, 1f} instead of null for the positions argument, same result. This might be a bug too.

Note that this is not a duplicate of this post nor this one. These are about incorrect gradient stops set in code which is not my case. It might be related to this one but I don't see how.

EDIT: Maybe this could be solvable by setting unequal positions to colors, but how can I calculate these exact positions?


Solution

  • I've been working to solve this more than 3 hours in total and well... turns out it was almost nothing. And it was in my code. The worst of it is I added a bounty and solved it 15 minutes later.

    I drew the gradient in a view with a certain padding and instead of this

    LinearGradient(0, 0, width, 0, colors, null, Shader.TileMode.CLAMP);
    

    I had to do this:

    LinearGradient(left, 0, right, 0, colors, null, Shader.TileMode.CLAMP);
    

    Somehow the gradient begins before the padding I added to my view, at (0, 0), which is 10 dip left of my gradient start, causing the offset.

    enter image description here

    It all makes sense now.