Sweep Gradient : What it is and its examples

Kaushik NP picture Kaushik NP · Jul 4, 2017 · Viewed 9.4k times · Source

I came across Sweep Gradient on Android and was intrigued if it could give me a better control over the Color spacing and transitions. Did a quick search and found almost nothing about it!!

The only few references I found (and they do not meet the criteria of coming even close to explaining it properly or comprehensively) are listed below :

So thats almost about it. Others are similar or disparagingly brief.


Few conclusions I have drawn so far (and maybe are wrong) :

  • Sweep Gradient are mainly used for Rings
  • They are used for similar transactions as the Angular sweep (not sure about this one) which talks about transaction similar to sweep of a clock's hand.
  • Very similar to Linear Gradients. The only thing I can think about for a difference between them is for the usage (like Rings).
  • Sweep deals with Center (again a strong reference towards the clock theory)

I know people may consider this as not really a technical question. But for me to work with Sweep Gradients or atleast know what they mean, the description has to come from somewhere. And please do provide the answers with some examples of usage of Sweep in cases other than Rings.

Answer

Attila Tanyi picture Attila Tanyi · Jul 12, 2017

The word gradient in this context (as in many graphics editors, including Photoshop) refers to a smooth transition between multiple colors, as opposed to using just a single color to fill an area.

The Android API provides 3 different gradients: LinearGradient, RadialGradient and SweepGradient.

These are all subclasses of Shader. You can set a Shader on a Paint object, and then draw any shape with that Paint. The shape will be filled with colors and transitions between them, according to the kind of the gradient.

For example:

output image of the code below

This image can be produced with this code:

Bitmap test = Bitmap.createBitmap(640, 200, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(test);
{ // draw a dark gray background
    Paint backgroundPaint = new Paint();
    backgroundPaint.setARGB(255, 24, 24, 24);
    c.drawPaint(backgroundPaint);
}
Path heart = new Path();
{ // prepare a heart shape
    heart.moveTo(110, 175);
    heart.lineTo(10, 75);
    RectF leftCircle = new RectF(10, 25, 110, 125);
    heart.arcTo(leftCircle, 180, 180);
    RectF rightCircle = new RectF(110, 25, 210, 125);
    heart.arcTo(rightCircle, 180, 180);
    heart.close();
}
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(18f);
int[] colors = {
        0xFFFFFF88, // yellow
        0xFF0088FF, // blue
        0xFF000000, // black
        0xFFFFFF88  // yellow
};
float[] positions = {0.0f, 0.33f, 0.66f, 1.0f};
{ // draw the left heart
    SweepGradient sweepGradient;
    { // initialize the sweep gradient
        sweepGradient = new SweepGradient(50, 50, colors, positions);
        paint.setShader(sweepGradient);
    }
    c.drawPath(heart, paint);
    c.drawText("SweepGradient", 50, 190, paint);
}
{ // draw the middle heart
    LinearGradient linearGradient;
    { // initialize a linear gradient
        linearGradient = new LinearGradient(250, 0, 350, 150, colors, positions, Shader.TileMode.CLAMP);
        paint.setShader(linearGradient);
    }
    heart.offset(210, 0); // move the heart shape to the middle
    c.drawPath(heart, paint);
    c.drawText("LinearGradient", 260, 190, paint);
}
{ // draw the right heart
    RadialGradient radialGradient;
    { // initialize a linear gradient
        radialGradient = new RadialGradient(550, 50, 100, colors, positions, Shader.TileMode.CLAMP);
        paint.setShader(radialGradient);
    }
    heart.offset(210, 0); // move the heart shape to the right
    c.drawPath(heart, paint);
    c.drawText("RadialGradient", 470, 190, paint);
}
{ // save the bitmap
    String filename = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.png";
    FileOutputStream out = null;
    try {
        out = new FileOutputStream(filename);
        test.compress(Bitmap.CompressFormat.PNG, 90, out);
    } catch (Exception e) {
    } finally {
        try {
            out.close();
        } catch (Exception e) {
        }
    }
}
  • So the LinearGradient is Linear Gradient in Photoshop, RadialGradient is Radial Gradient, and SweepGradient is Angular Gradient, as described in your 3rd reference. I recommend trying these in an image editor first (all popular image editors have these tools), and you'll quickly get the idea of how they work.

  • You can use these gradients in an XML drawable too (like in your 4th reference), with a limitation of using 3 colors maximum.

  • In a SweepGradient, when providing positions, the 0.0 point is at 3 o'clock, going clockwise (with 0.25 being at 6 o'clock, 0.5 at 9 o'clock, 0.75 at 12 o'clock, and 1.0 back at 3 o'clock).

About your conclusions:

  • As you can see, any shape can be drawn with a SweepGradient, not just a ring. Even the labels are drawn with the gradients in the example above.
  • Yes, the clock's hand analogy is spot on.
  • In usage, SweepGradient is very similar to LinearGradient, except you don't need to provide a TileMode, because you cannot run outside of the bounds of your color list.
  • Yes, you need to provide the coordinates of the center point.

I hope this clears it up.