Kahibaro
Discord Login Register

16.1 ImageView and Drawable Resources

Understanding ImageView in Android

In Android apps, images are usually shown on the screen using the ImageView class. ImageView is a type of View that is specialized for displaying images from different sources, such as drawable resources, files, or URLs. In this chapter you focus on using ImageView together with drawable resources that are bundled with your app.

You normally define an ImageView inside an XML layout file. A simple example looks like this:

<ImageView
    android:id="@+id/logoImage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/app_logo"
    android:contentDescription="@string/app_logo_desc" />

The android:src attribute points to a drawable resource that will be displayed. The android:contentDescription attribute is important for accessibility. Screen readers use this text to describe the image to users who cannot see the screen.

ImageView has two main attributes for setting the image. The first is android:src, which sets the actual image content. The second is android:background, which sets a background behind the image content. If both are used, the background is drawn first, then the source image is drawn on top.

When you work with images, sizes matter. If your layout uses wrap_content for width and height, the ImageView will measure itself according to the image size, affected by the selected scale type. If you use a fixed dimension or match_parent, the image will be resized according to how you configure the ImageView.

ImageView Scale Types

Images rarely match the exact size of their ImageView. The scale type tells Android how to fit the image into the available space. You set the scale type in XML using android:scaleType or in Kotlin code using imageView.scaleType.

Some of the most common scale types are:

center keeps the image at its original size and centers it inside the view. Parts of the image can be cut off if it is larger than the view.

centerCrop scales the image so that the view is completely filled. It keeps the image aspect ratio. Some parts of the image may be cropped if the aspect ratio of the image and the view are different.

centerInside scales the image down only if it is larger than the view, keeping the aspect ratio. The whole image remains visible, but there may be empty space around it.

fitCenter scales the image so that it is completely visible inside the view and is centered. The aspect ratio is kept. Empty space can appear on at least one side.

fitXY stretches or squashes the image to exactly match the width and height of the view. The aspect ratio is not preserved.

You can configure a scale type in XML like this:

<ImageView
    android:id="@+id/bannerImage"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="centerCrop"
    android:src="@drawable/banner" />

When you choose a scale type, think about what matters more: showing the entire image or filling the available space. For photos, centerCrop is common for banners and headers. For icons or logos, fitCenter or centerInside often works best because you avoid distortion and keep everything visible.

What Are Drawable Resources

Drawable resources are images or graphics that your app can draw on the screen. They are stored in the res/drawable* folders and compiled into the app. You reference them with the @drawable/... notation in XML and with the R.drawable... identifier in Kotlin.

Drawables can be simple bitmap image files, scalable vector graphics, shapes defined in XML, or more advanced drawables like selectors and state lists. Each type has different strengths. For now, it is enough to understand that all of them live in the drawable resource folders, and all can be shown inside an ImageView.

You do not place raw image files directly anywhere in the project. If you want Android to manage them as resources, they must go into the correctly named res subdirectories. The build system processes the resources and generates IDs so you can access them from code.

Drawable resource names must use only lowercase letters, digits, and underscores. They cannot start with a digit and cannot contain spaces or uppercase letters.

If you use an invalid name, your project will not compile.

Drawable Resource Directories

Inside the res folder there are several drawable directories. They help Android choose the right resource depending on screen density or other device characteristics. For images related to density, the usual folders are:

drawable-mdpi for medium density screens.

drawable-hdpi for high density screens.

drawable-xhdpi for extra high density screens.

drawable-xxhdpi and drawable-xxxhdpi for even higher densities.

These qualifiers allow you to provide multiple versions of the same image. Android selects the resource that best matches the current device. If you only provide one version in the base drawable folder, Android scales it automatically, but quality may not be ideal on all screens.

As long as the file names match exactly across these folders, Android treats them as the same resource. For example, if you have icon_home.png in drawable-mdpi, drawable-hdpi, and drawable-xhdpi, you can reference it simply with @drawable/icon_home. The system decides which file to use.

For vector graphics, the usual directory is simply drawable. Vector drawables automatically scale to different densities, so you do not need a file per density.

Bitmap Drawables vs Vector Drawables

The two most common types of image resources are bitmap drawables and vector drawables.

Bitmap drawables are based on image files like PNG or JPEG. They have a fixed resolution. If you scale them up too much, they look blurry. You often need to provide multiple bitmap sizes for different densities. Bitmaps are suitable for photos and complex images that cannot be represented as simple shapes.

Vector drawables are XML descriptions of shapes, paths, and colors. They are resolution independent. Android can scale them to any size and they stay sharp. Vector drawables work very well for icons, logos, and simple illustrations with clean lines.

You usually get vector drawables through the Vector Asset tool in Android Studio or by importing SVG files that can be converted. Vector drawables use less space in your APK or AAB if you have many density variations. However, very complex vectors can be more expensive to draw at runtime.

You reference both bitmaps and vectors in the same way in XML:

android:src="@drawable/ic_star"

Android does not require you to know which type it is in most cases. It handles loading the right drawable behind the scenes.

Adding Drawable Resources to Your Project

To add image resources to your project, you usually place them into the correct drawable folders via Android Studio. For bitmap images you can drag files into the res/drawable folder. Android Studio offers to move them into a specific density folder or leaves them in the base drawable directory.

For vector drawables you often use the built in tool. Right click on res, choose to create a new Vector Asset, then pick from the Material icon set or import an SVG. Android Studio generates an XML file in the drawable directory that describes the vector.

Once an image is in the drawable directory, it becomes available through the R class. You can access it in Kotlin as R.drawable.file_name, where file_name is the resource name without the file extension.

If you add or rename drawable files while the project is open, Android Studio automatically regenerates the R class so your code can reference the new resources.

Using Drawables in XML

The most common place to use drawables in XML is in ImageView with android:src. However, drawables are not limited to images. Many views can use them as backgrounds or icons.

You can use a drawable as a background:

<ImageView
    android:id="@+id/avatarImage"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:background="@drawable/avatar_border"
    android:src="@drawable/avatar_photo" />

Here the avatar_border could be a shape drawable defined in XML that draws a circle or a rounded rectangle, and avatar_photo could be a bitmap or vector drawable.

Text based views like TextView and Button can also use drawables. They can show images next to text using attributes like android:drawableStart or android:drawableTop. Internally these are still drawable resources, and you reference them as @drawable/....

You can also use drawable resources in other XML files like styles, themes, or selectors. As long as you are inside res XML, you can refer to a drawable by using @drawable/ followed by its name.

Setting Images Programmatically

You often need to change the image of an ImageView at runtime. For example, you might display a different icon based on user input or based on fetched data. In Kotlin you can set the image in several ways.

The most common approach for drawable resources is to use setImageResource:

val imageView: ImageView = findViewById(R.id.statusImage)
imageView.setImageResource(R.drawable.ic_status_ok)

This loads the drawable resource and sets it as the image content. If you later want to change it, you simply call setImageResource again with a different ID.

You can also use setImageDrawable if you already have a Drawable object. To obtain a drawable, you can use ContextCompat.getDrawable:

val drawable = ContextCompat.getDrawable(this, R.drawable.ic_warning)
imageView.setImageDrawable(drawable)

Another option for bitmaps is setImageBitmap, which expects a Bitmap object. This is useful when you have created or loaded a bitmap yourself, for example from a file. Handling raw bitmaps includes more complexity regarding memory usage and is treated elsewhere in more detail.

Whenever you change the image programmatically, the ImageView keeps using the same scale type and layout parameters that you defined in XML or in code. Only the actual drawable content changes.

Tinting and Coloring Drawables

Very often you want to reuse the same drawable resource but in different colors. This is especially common for vector icons and UI elements that should adapt to the app theme or state. Tinting lets you apply a color on top of a drawable.

If your drawable supports tinting, and if you are using appropriate app compat libraries, you can set a tint in XML on the ImageView. For example:

<ImageView
    android:id="@+id/favoriteIcon"
    android:layout_width="24dp"
    android:layout_height="24dp"
    android:src="@drawable/ic_favorite"
    android:tint="@color/colorAccent" />

This displays the ic_favorite icon using the accent color defined in your resources. If you change the theme color, the tinted icon updates automatically when it is redrawn, assuming you use resource based colors.

You can also apply tints in Kotlin code using ImageViewCompat.setImageTintList or directly with the imageTintList property on newer APIs:

val imageView: ImageView = findViewById(R.id.favoriteIcon)
val color = ContextCompat.getColor(this, R.color.colorAccent)
imageView.imageTintList = ColorStateList.valueOf(color)

Tinting works best with vector icons that use a single color or shapes defined in XML. Complex photos do not benefit from tinting in the same way, although you can still apply color filters.

Density, Quality, and Performance

Using drawable resources correctly affects both the visual quality and performance of your app. Large bitmap images consume more memory. If you show many large images at the same time, your app can run out of memory and crash. Even when you use ImageView, which manages rendering for you, the underlying bitmap still occupies space in memory.

Drawable density directories help control how much scaling happens. If you only ship low resolution images and the system needs to scale them up a lot on a high resolution screen, the result looks blurry. On the other hand, if you only ship extremely large images and scale them down all the time, you waste storage and memory.

Vector drawables help with density issues for icons and simple graphics, since one XML file serves all densities with sharp results. However, very large or overly detailed vectors may cost more processing during drawing.

When you design your app UI, prefer vector drawables for icons and simple shapes. Keep bitmap images at appropriate sizes. Avoid loading images that are much larger than needed for the ImageView. This balance improves both appearance and resource usage.

Accessibility and Image Content

Every important ImageView in your app should have a meaningful contentDescription. This text is read aloud by screen readers for users who rely on assistive technologies. For decorative images that do not convey information, you can set contentDescription to @null to signal that assistive tools should ignore them.

You define this in XML:

<ImageView
    android:id="@+id/profileImage"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:src="@drawable/profile_placeholder"
    android:contentDescription="@string/profile_picture_desc" />

For images that are purely decorative, like background patterns or separators, you might write:

android:contentDescription="@null"

This keeps the accessibility experience clean and focused only on elements that matter.

Summary

You now know how ImageView works together with drawable resources that are packaged with your app. You saw how to place images into drawable folders, how to reference them from XML and Kotlin, how to choose appropriate scale types, and how to tint icons to match your app style. Later chapters will build on this foundation and show how to load images from external sources and handle more complex media scenarios.

Views: 1

Comments

Please login to add a comment.

Don't have an account? Register now!