Lesson 162. Graphics. Drawable. Shape, Gradient.

Lesson 162. Graphics. Drawable. Shape, Gradient.

In this lesson:

– study the drawable-tag shape

After getting acquainted with Bitmap, we move on to another key object of the drawing – Drawable.

Drawable is an abstract container for a graphic object. His main abstract skill is that he can draw his content on the canvas he was given. But what exactly he draws, depends on the implementation. This can be, for example, the same Bitmap if we are using a BitmapDrawable object. Or it could be a simple geometric figure if we use ShapeDrawable.

We can create drawable objects ourselves in the code. But for some of them we can create a description in xml files, in the res / drawable folder. And when we need it, we will specify the file id, the system will parse it itself and create the object we want.

The most common use of Drawable is the background property that each View has. As a value, you can specify the RGB color or resource id from the res / drawable folder there. Next, the system itself by this value will determine the type and further:

– if it’s a color, it will create a ColorDrawable,
– if this is the id of the image in res / drawable, then it will create BitmapDrawable
– if this is an id of an xml file in res / drawable, then parse it and return the corresponding Drawable heir: StateListDrawable, AnimationDrawable or some other.

As a result, View will receive its Drawable object and be able to draw it.

In general, as you understand, Abstract Drawable has several successors to implementations, and in the coming lessons we will look at them. Let’s start with the ones that can be described in xml. Behind it is a separate article in Help. There are, however, a couple of copycat mistakes, but the rest is true.

In this lesson, we’ll look at the shape>

Let’s create a project:

Project name: P1621_DrawableShape
Build Target: Android 4.4
Application name: DrawableShape
Package name: ru.startandroid.develop.p1621drawableshape
Create Activity: MainActivity

res / layout /main.xml:


let’s create a file

res / drawable /shape.xml:


The root tag is shape, and it has the shape attribute of the same name, in which we specify the type of figure. we have specified rectangle is a rectangle.

Next, inside the shape tag, is the stroke tag, which allows us to specify the characteristics of the contour line (perimeter) of the shape. We set the width (width) to 1dp and black (color).


package ru.startandroid.develop.p1621drawableshape;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;

public class MainActivity extends Activity {

ImageView imageView;
  protected void onCreate(Bundle savedInstanceState) {
    imageView = (ImageView) findViewById(R.id.imageView);
  private void setDrawable() {


ImageView doesn’t display anything yet.

run the program

We see an ImageView with a gray background

Let’s rewrite the setDrawable method:

  private void setDrawable() {

As drawable we will pass our shape file


ImageView now displays a rectangle with a black outline.

Let’s see what other figures are available to us.

Let’s rewrite shape.xml:


The value of the shape = attribute ovalThis is an ellipse

In our case, the circle came out because ImageView is square.

value line will give us a horizontal line


There is also a figure ring (ring), But about him a little later.

Let’s return to the stroke tag. Let’s add parameters to it.


Width – 4dp, color – blue. The dashWidth and dashGap options will make the contour line dashed. dashWidth specifies the length of the dotted line, and dashGap specifies the distance between the lines

Add fill, this uses the solid tag


The solid tag has a color attribute that allows you to specify the fill color of the shape. We have indicated it in green.

By default, the figure occupies all the space available to it, but we can explicitly specify its size using the size tag.


We use the size tag with the width and height attributes

The figure is now 100×100 in size and no longer occupies all the space available to it.

Note that the display mode depends on scaleType y ImageView.

The padding tag allows us to put the indentation value inside the shape. This is relevant, for example, for TextView. Indentation will be taken into account when placing the text.


We have specified different indents from all 4 sides.

If we now hang this figure as the background for TextView, the result will be this

As a fill, we can use not one color but a gradient of two or three. The gradient tag is used for this purpose.


The gradient tag specifies two color attributes: startColor and endColor.

The result is a gradient that changes from the first color to the second.

The gradient does not necessarily have to go from left to right. We can specify the angle of direction. To do this, the gradient tag has an angle attribute


Angle indicates angle 225. Angle 0 indicates left-to-right direction, 90 from bottom to top, etc. The angle must be a multiple of 45.

The result is a right-to-left-to-left angle.

The gradient tag allows you to specify a third color that will wedge between the start and end colors.


In the centerColor attribute we specify blue color and it will be in gradient between red and green.

The gradient can be of different types. We have considered the default linear type. There are two other types: radial and sweep.


The radial type will give us a circular gradient, and in the gradientRadius parameter we have to specify the radius of the circle.

We can specify the point of the center of the circular gradient with the attributes centerX and centerY. The values ​​of these attributes must be from 0 to 1.


The center of the gradient will be at the point (0.2, 0.2) if you take the dimensions of the figure per unit.

Now let’s see what the sweep gradient looks like.


You can also use the centerColor, centerX, and centerY attributes for this type of gradient.

For a rectangle shape, we can smooth the corners. This is the responsibility of the corners tag.


The radius attribute allows you to set the radius of curvature at once for all angles.

You can set your radius for each corner individually.



It remains for us to consider the fourth figure – the ring. To get it, you need to specify a ring value in the shape attribute. For the ring, we can adjust two parameters: the size of the inner radius and the thickness of the ring. Moreover, we can specify these two parameters in absolute and relative terms.


innerRadius – allows you to specify the inner radius and thickness the thickness of the ring. The useLevel attribute, which we do not know yet, must be false, otherwise this figure is not displayed to me.

A circle with an inner radius = 50dp and a thickness = 40dp was displayed.

Let’s try to specify the thickness of the ring in the relative value. We use thicknessRatio instead of thickness. In this attribute we specify how many times the thickness of the ring will be less than its width.


Ring width = 200 dp, this is specified in the size tag. thicknessRatio = 10, then the thickness of the ring = 200 dp / 10 = 20dp.

Now let us note the inner radius in relative terms. To do this, instead of innerRadius we use innerRadiusRatio. The innerRadiusRatio attribute specifies how many times the inner radius is less than the width of the ring.


Ring width = 200 dp. innerRadiusRatio = 3, hence inner ring radius = 200 dp / 3 = 67dp.

As you can see, the ring may not take up all its size. It depends on the values ​​we set for the inner radius and thickness.

Relative size attributes have a default value. That is, if we do not explicitly specify a value for innerRadiusRatio, then by default it will be 3 and thicknessRatio by default is 9. Let’s see how it looks


We specified only the inner radius. And the thickness will be calculated based on the default thicknessRatio value, ie 9.

Now we will not indicate the info on the inner radius.


We have specified only the thickness of the ring, and the inner radius will be calculated based on the innerRadiusRatio default value = 3.

Now let’s try not to specify the size of the inner radius and thickness, and see what happens.


We see that the ring did not take all the 200 dp in height that we gave it in the size tag. Why? Let’s count based on the default value.

Inner radius = 200/3 = 67. Thickness = 200/9 = 22. That is, the diameter of the ring is = 22 + 67 * 2 + 22 = 178.

Let’s try to fit the size of the ring to any space he chooses.


Now the radius will be 200 / 2.5 = 80, and the thickness = 200/10 = 20. The diameter of the ring = 20 + 80 * 2 + 20 = 200.

This is also visible on the chest. The ring is now one ImageView in size = 200.

Absolute attributes (innerRadius and thickness) have priority over relative (innerRadiusRatio and thicknessRatio).


Although the root tag is called shape, but when it is parsed, it creates not GradientDrawable, not ShapeDrawable.

Also, we can create this object ourselves programmatically.

rewrite the method setDrawable:

  private void setDrawable() {
    GradientDrawable drawable = new GradientDrawable(GradientDrawable.Orientation.BL_TR, 
        new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.CYAN, Color.MAGENTA });
    drawable.setStroke(10, Color.BLACK, 20, 5);

The set * methods allow us to set almost all the same parameters as in the xml file.

But there are also differences. For example, I did not find the GradientDrawable to be set to ring sizes. On the other hand, we at GradientDrawable can specify more than three colors for a gradient.

That is, basically xml and java creation are equivalent, but there are some nuances.

In the next lesson:

– learn drawable tags: , ,

Discuss in the forum [6 replies]

Leave a Comment