Android: using radial gradients in canvas – glowing dot example

Recently i wanted to create a glowing version of a dot, to indicate the active state. Really its just to get the effect of a glowing LED. As you can see its a symbolic representation.

So i created it using a Paint that contains a Shader which is made from a RadialGradient. What i really mean is:  drawCircle(Paint(Shader(RadialGradient)))

In this example, the center of the gradient is the same as the center of the circle, and one color is used twice in the gradient. The radius of the glowing dot is nearly twice that of the plain circles.

Here is how to do it, with the following reservations:

  • the gradient may appear very banded, not smooth – especially when it is one color. This is not necessarily due to the gradient itself, but the way it is expressed onto the screen by the device. The above image is from a device screenshot, but on the actual device, it didnt look so smooth.
  • when the gradient fades to transparency over a background, the appearance can be very bad on some screens (such as mine). Fix this problem by having the background color as the gradient end color, NOT “Color.TRANSPARENT”. In the above picture, the background color was used as the final color in the gradient.

Important:

  • Radial gradients have their own center. You can have the center of the gradient anywhere on – or off – the canvas. Within the shape you draw you will see that part of the gradient “exposed” by the shape bounds. In this example the center of the gradient is in the center of the shape, to create a glowing button effect.
  • Dont expect the gradient to look perfect – try it out and see if it suits your needs.
  • Try to do as much as possible before the onDraw is called. This is because setting up gradients and declaring things within onDraw will slow down the draw. Set up the dimensions for the gradient and paint in onSizeChanged. set up everything else in onResume. Call drawCircle or whatever, in the onDraw method
  • declare your variables at the top before onCreate, so that the different parts of your gradient can be assembled by different methods in the class.

This code is used within an activity that contains a view class with onDraw. The canvas.drawCircle() draws directly to the view. It is easily adapted to draw onto a canvas that then is used to fill a bitmap.

In this example, i have set the center of the gradient to the center of the drawn circle, and the radius of the gradient is the same as the circle. The gradient will end at the edge of the drawn circle.

The code for the gradient:

  • variable declarations before onCreate()

float[] stopsGradient;
int[] colorsGradient;
float xGC;
float yGC;
float xC;
float yC;
float rC;
RadialGradient rgName ;
float rgRadius

in onSizeChanged, if coordinates depend on screen size – otherwise put in onResume()

stopsGradient = new float[] { 0, 0.5f, 1 }; // the 3 points correspond to the 3 colors
colorsGradient  = new int[] { getResources().getColor(R.color.color_fg), getResources().getColor(R.color.color_fg), getResources().getColor(R.color.color_background) };
xGC = width/2; // x for the gradient center
yGC = height/2;  // y for the gradient center
xC = width/2; // x for the circle center
yC = height/2;  // y for the circle center
radialGradient = new RadialGradient(xGC,yGC,rgRadius,colorsGradient, stopsGradient ,Shader.TileMode.CLAMP);

  • the stopsGradient and colorsGradient work together. these 2 variables hold the colors that should appear at certain points in the gradient. In this example, the first 2 colors are the same. From the center of the radial gradient, to the first stop (0.5 = half way) is a gradient that appears as one color, then from halfway, there is a visible gradient from the second color to the third color.
  • i use the example of calling the colors from the color resources. You can also just use something like Color.BLUE or 0x7733ff22, But, use a resource so that changing color values is easy.
  • one Radial Gradient is required for each different gradient center, because the center coordinates are contained in the RadialGradient statement.
  • read more about the tile modes available, by searching the google developer docs.

in onResume()

paint = new Paint();
paint.setDither(true);
paint.setAntiAlias(true);
paint.setShader(radialGradient);

  • the radial gradient is set as the shader for the paint. no separate shader statement is needed.
  • dithering is an effect used in printing images. take a magnifying glass to a printed image to see what i mean. Sometimes it improves gradients, sometimes not.
  • anti-aliasing makes edges look smoother, you can see the effect at the edge of the plain dots in the image. rather than cutting part of a pixel off, it reduces the drawn pixel opacity.

only this in onDraw()

canvas.drawCircle(xC,yC,rC,paint)

END

Android: using radial gradients in canvas – glowing dot example