Color, Bitmap, and VectorDrawable are types of Drawable objects used in Android development. They represent colors, images, and vector graphics, respectively, and are essential for creating various visual elements within the user interface.
Color
A color is represented as an integer containing four distinct values, delineating the opacity (referred to as alpha) and the intensity of the red, green, and blue components. Consequently, any Kotlin integer can serve as a valid color representation.
For instance, the expression 0xFF8C5AFF.toInt() denotes a color that is entirely opaque (FF), predominantly red (8C), with a moderate amount of green (5A), and significant blue (FF).
This color can also be denoted in XML format as either #8C5AFF or #FF8C5AFF. It's noteworthy that the alpha component is discretionary, and unlike Kotlin numeric literals, XML color representations are inherently opaque.
As previously discussed in the section concerning Values, color resources play a pivotal role. For instance, the color resource
<color name="green_lime">#CDDC39</color> can be accessed via ContextCompat.getColor(context, R.color.green_lime). This invocation retrieves the color from the application's resources and is synonymous with the Kotlin expression 0xFFCDDC39.toInt().
Colors find utility in various applications. Whether specified as:
android:background="@color/green_lime"setBackgroundColor(0xFFCDDC39.toInt())setBackgroundResource(R.color.green_lime)
these methods essentially equate to setBackground(ColorDrawable(0xFFCDDC39.toInt())) at the implementation level.
Color selector
In contrast to attributes such as background, which typically accept Drawable objects, there exist several properties within the Android framework that do not inherently operate with Drawables. These include properties like backgroundTint of a View, as well as textColor, hintTextColor, and drawableTint of a TextView.
While colors serve as appropriate values for these properties, an alternative option exists: the ColorStateList, commonly referred to as a color selector. This resource facilitates the definition of multiple colors corresponding to different states of a View. Below is an example of such a selector, depicted in the resource file res/color/button_background_tint.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#AC8AFF"/>
<item android:state_focused="true" android:color="#6C3ADF"/>
<item android:state_enabled="false" android:color="#AAAAAA"/>
<item android:color="#8C5AFF"/>
</selector>In this selector, the "Default" state corresponds to an indigo-purple hue, symbolized by a square of that color. When the View is disabled, the color shifts to a gray square, indicating the "disabled" state. The "focused" state is represented by a darker shade of indigo-purple, while the "pressed" state exhibits a lighter indigo hue.
The versatility of color selectors extends beyond merely defining colors for View properties like textColor to also encompass Drawable properties such as background. This is evidenced by the fact that referencing a color selector, such as android:textColor="@color/button_background_tint", can be equally valid for both color and Drawable attributes.
When fetching such a resource programmatically using ContextCompat, the return types differ based on the context: ContextCompat.getColorStateList(context, R.color.button_background_tint) yields a ColorStateList, while ContextCompat.getDrawable(context, R.color.button_background_tint) provides a ColorStateListDrawable. Furthermore, invoking getColor on a ColorStateList will yield the "default color" defined within the selector.
Expressing the color selector example provided earlier in Kotlin showcases an alternative syntax, highlighting a different order compared to XML. Here, the first argument enumerates all possible states, while the second lists their corresponding colors. Additionally, negation (-some_state) serves as the equivalent for the condition when a particular state is false.
ColorStateList(
arrayOf(
intArrayOf(android.R.attr.state_pressed),
intArrayOf(android.R.attr.state_focused),
intArrayOf(-android.R.attr.state_enabled),
intArrayOf()
),
intArrayOf(
0xFFAC8AFF.toInt(),
0xFF6C3ADF.toInt(),
0xFFAAAAAA.toInt(),
0xFF8C5AFF.toInt()
)
)It's crucial to note the significance of the order in defining states within the selector. Android evaluates states sequentially from top to bottom, thus necessitating that the default state remains as the last entry. This ensures proper state matching behavior when employed within application interfaces.
Bitmap
Bitmaps serve as digital representations of images, composed of a grid of pixels, each pixel representing a specific color. Commonly encountered in raster file formats such as PNG, GIF, WEBP, or JPEG, these formats store image data in a way that can be decoded into a Bitmap using various BitmapFactory.decode* methods available in Android development.
In practical application, Bitmaps offer a wide range of functionalities. They can act as versatile intermediate buffers for rendering complex graphics or as straightforward visual content displayed within ImageView components in Android applications. For instance, in image editing applications, Bitmaps are often manipulated to apply filters, add text overlays, or draw shapes on images.
In Android development, ImageView components are frequently utilized for displaying images within the user interface (UI). The setImageBitmap(bitmap) method directly assigns a Bitmap object as the content of an ImageView, enabling seamless integration of image data into the UI. Alternatively, the setImageResource(R.drawable.mountains) method references image resources stored within the app's resources directory and internally converts them into BitmapDrawable objects, facilitating their display within the ImageView.
Understanding Bitmaps and their usage is fundamental in the development of visually rich applications, as they form the cornerstone of image processing and presentation within the Android ecosystem.
Vector
VectorDrawables are images in Android that are defined using vector graphics, which means they are created using lines, curves, and shapes rather than pixels like traditional images. They are similar to SVG (Scalable Vector Graphics) images used on the web.
Here's an example of how you might describe a simple bookmark icon in XML:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M4,4v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2H6C4.9,2 4,2.9 4,4zM11,4h5v6.12c0,0.39 -0.42,0.63 -0.76,0.43L13.5,9.5l-1.74,1.05c-0.33,0.2 -0.76,-0.04 -0.76,-0.43V4z"/>
</vector>This XML code describes a vector graphic that represents a bookmark icon. It specifies the width and height of the icon, as well as the coordinates of the points, lines, and curves that make up the icon's shape.
In Android Studio, you can easily import existing SVG files and convert them to VectorDrawables (File → New → Vector Asset). This process simplifies the creation of vector graphics for your app without needing to manually write XML code.
VectorDrawable class is used to handle vector graphics. Unlike colors or images, there isn't a specific class for vectors. Also, you can't create vector drawings programmatically using code; you have to use XML files to define them. This means you can't dynamically generate vector graphics at runtime, they need to be defined beforehand in your app's resources.
Conclusion
Understanding color, Bitmaps, and VectorDrawables is essential in Android development. Colors are represented as integers with alpha, red, green, and blue components, used for visual elements. Bitmaps handle image data, commonly used in ImageView components. VectorDrawables are scalable graphics defined using vectors, offering flexibility and sharp visuals.