Lesson 165. Graphics. BitmapShader, LinearGradient, RadialGradient, SweepGradient
Android Lessons

Lesson 165. Graphics. BitmapShader, LinearGradient, RadialGradient, SweepGradient


In this lesson:

– We study Shader subclasses

Using Shader class subclasses, we can draw. To do this, transfer the Shader object to the setShader brush method, and the brush will use a shader drawing to draw objects. Consider the existing heirs of the Shader class.

I will do examples in Activity. All graphics will be implemented in the DrawView class.

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new DrawView(this));
  }

  class DrawView extends View {

    public DrawView(Context context) {
      super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);
    }

  }
}

BitmapShader

To create this shader, you must pass it to Bitmap and specify the vertical and horizontal TileMode. For details on TileMode modes, see Lesson 163.

rewrite the class DrawView:

  class DrawView extends View {

    Paint paint;
    Bitmap bitmap;
    Bitmap scaledBitmap;

    public DrawView(Context context) {
      super(context);
      Shader shader = createShader();
      paint = new Paint(Paint.ANTI_ALIAS_FLAG);
      paint.setShader(shader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
      canvas.drawARGB(80, 102, 204, 255);
      canvas.drawRect(100, 100, 400, 300, paint);
      canvas.drawCircle(300, 400, 100, paint);
    }

    private Shader createShader() {
      bitmap = BitmapFactory.decodeResource(getResources(),
          R.drawable.ic_launcher);
      BitmapShader shader = new BitmapShader(bitmap,
          Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
      return shader;
    }

  }

We read ic_launcher in Bitmap, create a shader and pass this shader to the setShader brush method. And using this brush we draw a square and a circle.

We used TileMode.REPEAT, so the image repeats throughout the available space.

You can apply a shader to a shader using a matrix (the lesson was about Lessons 144).

rewrite the method createShader:

    private Shader createShader() {
      bitmap = BitmapFactory.decodeResource(getResources(),
          R.drawable.ic_launcher);
      BitmapShader shader = new BitmapShader(bitmap,
          Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
      Matrix matrix = new Matrix();
      matrix.postScale(2, 1.5f);
      matrix.postRotate(45);
      shader.setLocalMatrix(matrix);
      return shader;
    }

In the matrix, we adjust the stretch and rotate and pass it to the shader using the setLocalMatrix method. see the result

You can stretch Bitmap all over the canvas

    private Shader createShader() {
      bitmap = BitmapFactory.decodeResource(getResources(),
          R.drawable.ic_launcher);
      bitmap = Bitmap.createScaledBitmap(bitmap, 480, 680, true);
      BitmapShader shader = new BitmapShader(bitmap,
          Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
      return shader;
    }

Using the createScaledBitmap method, create a copy of the canvas-sized bitmap.

LinearGradient

This shader allows us to get a gradient. His class has two constructors. We are both asked to provide them with TileMode and the coordinates of a line that will set the direction, start and size of the gradient at the same time.

The difference is the way colors are specified for the gradient. One designer asks us to give him two colors. He draws a gradient behind it.

    private Shader createShader() {
      LinearGradient shader = new LinearGradient(0, 0, 100, 20,
          Color.RED, Color.GREEN, Shader.TileMode.MIRROR);
      return shader;
    }

Specify red and green colors. The line is specified by (0,0) – (100,20). The gradient will go in the direction of the line and will be the size of the length of that line. As TileMode we pass MIRROR.

Another constructor allows you to specify an array of colors and their positions in the gradient.

    private Shader createShader() {
      LinearGradient shader = new LinearGradient(0, 0, 100, 20,
          new int[] { Color.RED, Color.BLUE, Color.GREEN }, null,
          Shader.TileMode.MIRROR);
      return shader;
    }

We pass an array of colors, and instead of an array of positions we pass null – the gradient itself distributes the colors evenly.

Now let’s try to position the items manually.

    private Shader createShader() {
      LinearGradient shader = new LinearGradient(120, 0, 380, 0,
          new int[] { Color.RED, Color.BLUE, Color.GREEN },
          new float[] { 0f, 0.5f, 1f }, Shader.TileMode.REPEAT);
      return shader;
    }

Note that I used TileMode REPEAT here. In this mode, the color gradient distribution will be better visible. Also, I slightly modified the coordinates of the line to make the gradient larger and more purely horizontal.

We transfer three positions in the array of positions (according to the number of colors). To understand what these positions mean, let’s take the size of the gradient (in our case, the width). And the positions will indicate where the gradient will be the maximum saturation of the corresponding color.

In our example, there are three colors: red blue, green. And three positions: 0, 0.5, 1. That is, red will be located at the beginning of the gradient (0), blue – in the middle (0.5), and green – at the end (1). The space between the flowers will be filled with the appropriate gradient.

We will change the position slightly and change the blue one to the right, thus increasing the area of ​​red-blue gradient and decreasing the area of ​​blue-green.

    private Shader createShader() {
      LinearGradient shader = new LinearGradient(120, 0, 380, 0,
          new int[] { Color.RED, Color.BLUE, Color.GREEN },
          new float[] { 0f, 0.7f, 1f }, Shader.TileMode.REPEAT);
      return shader;
    }

For blue the position was equal to 0.7 and it went to the right.

For the RadialGradient class, we specify the center and the radius and the gradient goes from the center to the edges. And SweepGradient is a gradient that goes in circles around the center. In these two classes, similarly to LinearGradient, there is a simple constructor where it is possible to specify two colors, but it is more difficult – with the possibility of specifying an array of colors and their ratios.

Examples of using xml variants of RadialGradient and SweepGradient can be found in Lesson 162.




Discuss in the forum [0 replies]

Leave a Reply

Your email address will not be published. Required fields are marked *