BarryBostwick
BarryBostwick

Reputation: 940

Android: How to draw a two dimensional gradient

I am looking to draw a gradient like this using Android's Canvas:

enter image description here

In the horizontal direction there is a gradient of two colors (red and blue). Then in the vertical direction there is a gradient of transparency (allowing the red and blue to show) to nothing (the absence of all color?).

I found this link on SO here which is close to what I want. But I cannot figure out how to make the bottom transparent.

How can this be accomplished in Android?

Upvotes: 1

Views: 4101

Answers (2)

Cary Clark
Cary Clark

Reputation: 11

Here's how to draw it in Skia using C++. The equivalent in Java on Android should be very similar.

SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
SkPoint horz[] = { { 0, 0 }, { 256, 0 } };
SkPaint paint;
paint.setShader(SkGradientShader::MakeLinear(horz, colors, nullptr, 2,
        SkShader::kClamp_TileMode));
canvas->drawPaint(paint);
paint.setBlendMode(SkBlendMode::kDstIn);
SkColor alphas[] = { SK_ColorBLACK, SK_ColorTRANSPARENT };
SkPoint vert[] = { { 0, 0 }, { 0, 256 } };
paint.setShader(SkGradientShader::MakeLinear(vert, alphas, nullptr, 2,
        SkShader::kClamp_TileMode));
canvas->drawPaint(paint);

gradient with fade

Upvotes: 1

Bartek Lipinski
Bartek Lipinski

Reputation: 31438

Those sort of "custom" gradients can sometimes be pretty annoying. To make it as painless as you can, you could use specially prepared drawable resource.

There are two main ways you can accomplish that with a drawable:

  1. Use two linear gradients
  2. Use two radial gradients

The first approach could be implemented like this:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:angle="315"
                android:centerColor="#4DFC0A00"
                android:endColor="#00FC0A00"
                android:startColor="#FC0A00" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:angle="225"
                android:centerColor="#4D5E17FD"
                android:endColor="#005E17FD"
                android:startColor="#5E17FD" />
        </shape>
    </item>
</layer-list>

And it would look like this (presented on white background):

linear gradients

You could still twitch centerX and centerY values for those gradients (defaults are 0.5)

The second approach could be implemented like this:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:centerX="0"
                android:centerY="0"
                android:gradientRadius="@dimen/gradient_width"
                android:endColor="#00FC0A00"
                android:centerColor="#80FC0A00"
                android:startColor="#FC0A00"
                android:type="radial" />
        </shape>
    </item>
    <item>
        <shape>
            <gradient
                android:centerX="1"
                android:centerY="0"
                android:gradientRadius="@dimen/gradient_width"
                android:endColor="#005E17FD"
                android:centerColor="#805E17FD"
                android:startColor="#5E17FD"
                android:type="radial" />
        </shape>
    </item>
</layer-list>

And it would look like this (presented on white background):

radial gradients

The one downside of the second approach is that you need to know your gradient width to set the gradientRadius.

You can also not set the gradientRadius to the full width, but like a 75% of it. It will give it a nice overlap but not too much.

Upvotes: 8

Related Questions