Calling setCompoundDrawables doesn't display the Compound Drawable
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
If you have ever called setCompoundDrawables() on a TextView or EditText and nothing appeared, you are not alone. This is one of the most common Android UI surprises, and the root cause is almost always the same: the drawable has no bounds. Understanding why Android requires explicit bounds and knowing the simpler alternative method will save you hours of debugging.
Why setBounds() Is Required
Android's setCompoundDrawables() method does not automatically measure or size the drawable you pass in. Unlike loading a drawable into an ImageView, where the system infers dimensions from the resource, compound drawables are positioned inline with text and Android needs you to explicitly define how much space the drawable should occupy.
When you call setCompoundDrawables(left, top, right, bottom), Android reads each drawable's getBounds() to determine its width and height. If you never called setBounds(), the bounds default to a zero-width, zero-height rectangle, so the drawable is technically there but invisible.
Here is the broken version in Java:
And here is the fix:
The setBounds(left, top, right, bottom) call defines the drawing rectangle. Using getIntrinsicWidth() and getIntrinsicHeight() tells Android to use the drawable's natural pixel dimensions.
The Easier Alternative: setCompoundDrawablesWithIntrinsicBounds
Because forgetting setBounds() is such a common mistake, Android provides setCompoundDrawablesWithIntrinsicBounds(). This method automatically calls setBounds() using each drawable's intrinsic dimensions, so you can skip that step entirely.
In Java:
There is also an overload that accepts resource IDs directly, which is even more concise:
In Kotlin, the same calls look like this:
For RTL (right-to-left) language support, prefer setCompoundDrawablesRelativeWithIntrinsicBounds(), which uses start/end instead of left/right:
Positioning: Left, Top, Right, Bottom
The four parameters in setCompoundDrawables(left, top, right, bottom) control where the drawable appears relative to the text. Pass null (or 0 for the resource ID overload) for any position you do not need.
You can control the gap between the drawable and the text with setCompoundDrawablePadding():
Tinting and Custom Sizing
To tint a compound drawable, use DrawableCompat.setTint() before attaching it:
If you need a custom size instead of the intrinsic dimensions, call setBounds() with your desired values and use setCompoundDrawables():
Common Pitfalls
- Forgetting to call
setBounds()when usingsetCompoundDrawables(), resulting in an invisible drawable. - Using
setCompoundDrawables()with left/right parameters in an RTL locale instead of the relative variants, causing the icon to appear on the wrong side. - Passing a
nulldrawable without realizingContextCompat.getDrawable()can return null if the resource ID is invalid. - Calling
setTint()withoutmutate(), which can change the tint on every view sharing that drawable. - Setting compound drawable padding in
dpbut passing raw integer pixels, leading to inconsistent spacing across screen densities.
Summary
setCompoundDrawables()requires you to callsetBounds()on each drawable first, otherwise the drawable renders with zero size and is invisible.setCompoundDrawablesWithIntrinsicBounds()handles bounds automatically and is the preferred method for most use cases.- Use the
Relativevariants (setCompoundDrawablesRelativeWithIntrinsicBounds()) to correctly support RTL layouts. - Control spacing with
setCompoundDrawablePadding()and tint withDrawableCompat.setTint()after callingmutate(). - For custom-sized drawables, manually set bounds to your desired dimensions and use the base
setCompoundDrawables()method.

