373

After I call the setCompoundDrawables method, the compound Drawable is not shown..

Drawable myDrawable = getResources().getDrawable(R.drawable.btn);
btn.setCompoundDrawables(myDrawable, null, null, null);

Any thoughts?

Rahul Tiwari
  • 6,851
  • 3
  • 49
  • 78
hunterp
  • 15,716
  • 18
  • 63
  • 115
  • 12
    As stated in the answers below, the variant of the method named `(..)WithIntrinsicBounds` needs to be called. On a side note, `padding` for the Compound Drawable must be set **after** this call to cause an effect – Dr1Ku Jun 27 '12 at 16:17
  • 8
    The [document](http://developer.android.com/reference/android/widget/TextView.html#setCompoundDrawables%28android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable%29) says: *The Drawables must already have had [`setBounds(Rect)`](http://developer.android.com/reference/android/graphics/drawable/Drawable.html#setBounds(android.graphics.Rect)) called.* –  Dec 15 '12 at 10:44
  • hi hunterp, just met you at coffee shop (Angel), now that I know you know what Android Drawables are (and perhaps you've hit memory out of error errors when working with many of them), I can tell you about some of the projects I've collaborated had to deal with this issue, check out https://github.com/JakeWharton/DiskLruCache (which I collaborated to make more android friendly) which is used by Picasso (https://github.com/square/picasso) – Gubatron Aug 07 '13 at 19:33
  • 1
    @Dr1Ku Actually I have it before and is works anyway. – Sotti Mar 06 '14 at 22:21
  • Please see this link https://stackoverflow.com/a/71966649/12272687 – Mori Apr 22 '22 at 09:43

11 Answers11

704

I needed to be using setCompoundDrawablesWithIntrinsicBounds.

Mr_Milky
  • 155
  • 9
hunterp
  • 15,716
  • 18
  • 63
  • 115
  • 9
    thankyou very much .. this works for me.. may i know whats the difference between these two ? – Arundas K V Jun 06 '14 at 07:13
  • 1
    @user1324936 The 'relative' version requires API 17, others can be used with previous versions – milosmns Mar 26 '15 at 14:47
  • 12
    @user1324936 setCompoundDrawablesWithIntrinsicBounds was added in **API Level 3** – Greg Ennis Apr 01 '15 at 21:47
  • I was using setCompoundDrawableRelativeWithIntrinsicBounds <- this one was added on API 17. Be careful of the intellisense. – Neon Warge Dec 21 '16 at 14:42
  • its working thanks. what's the difference between them – Punithapriya Mar 10 '17 at 11:15
  • 1
    SetcCompoundDrawable ducomentation: Sets the Drawables (if any) to appear to the left of, above, to the right of, and below the text. Use null if you do not want a Drawable there. The Drawables must already have had setBounds(Rect) called. setBounds() is not called on your drawables. – Mahendra Chhimwal Aug 08 '17 at 10:52
76

Use This (I tested). It works good

Drawable image = context.getResources().getDrawable( R.drawable.ic_action );
int h = image.getIntrinsicHeight(); 
int w = image.getIntrinsicWidth();   
image.setBounds( 0, 0, w, h );
button.setCompoundDrawables( image, null, null, null );
mmBs
  • 8,421
  • 6
  • 38
  • 46
aryan bahmani
  • 891
  • 6
  • 8
  • 1
    This is useful when targeting APIs lower than 17, since `EditText#setCompoundDrawablesWithIntrinsicBounds` requires at least API 17. – Krøllebølle Feb 21 '16 at 12:49
  • 6
    Can you provide a source for that? All the documentation I've seen indicates this has been [available since API 1](https://developer.android.com/reference/android/widget/TextView.html). – kurifu Oct 18 '16 at 22:58
52

Image is blank because it hasn't got specified bounds. You may use setCompoundDrawables() but before you should specify image's bounds, using Drawable.setBounds() method

teoREtik
  • 7,886
  • 15
  • 46
  • 65
  • 1
    Best answer because you actually provide the reasoning as to why setBounds is important. – Andy Dec 10 '17 at 16:05
  • @Andy Exactly, hate these top answers with 800 votes that just copy pasted one code line without any words – Big_Chair Apr 14 '19 at 08:53
48

Example set to the top:

view.setCompoundDrawablesWithIntrinsicBounds(
    null,
    getResources().getDrawable(R.drawable.some_img),
    null,
    null
);

arguments order: (left, top, right, bottom)

Andrew
  • 36,676
  • 11
  • 141
  • 113
  • 1
    this should be the accepted answer, in my case using button. and it workeds as expected!!! It also backward compatibility. – mochadwi Mar 17 '19 at 06:57
24

A little bit simpler again:

Drawable image = context.getResources().getDrawable(R.drawable.ic_action );
image.setBounds( 0, 0, image.getIntrinsicWidth(), image.getIntrinsicHeight() );
button.setCompoundDrawables( image, null, null, null );
Alecs
  • 2,900
  • 1
  • 22
  • 25
20

The Image is not shown as you didn't specify the bounds, so you have 2 options here.

1st Method

Use setCompoundDrawablesWithIntrinsicBounds method, as shown below

Drawable myDrawable = getResources().getDrawable(R.drawable.btn);
btn. setCompoundDrawablesWithIntrinsicBounds(myDrawable, null, null, null);

2nd Method

You can apply bounds to the drawable before applying to the TextView, as shown below

Drawable myDrawable = getResources().getDrawable(R.drawable.btn);
myDrawable.setBounds( 0, 0, myDrawable.getIntrinsicWidth(), myDrawable.getIntrinsicHeight());
btn.setCompoundDrawables(myDrawable, null, null, null);

That's it.

Asad Ali Choudhry
  • 4,985
  • 4
  • 31
  • 36
  • Nice you actually included examples and the pre API 17 implementation which more directly addressed the setCompoundDrawables method. – Androidcoder Jul 05 '22 at 15:08
11

It is deprecated in API 22.

This code is useful for me:

Drawable drawable = ResourcesCompat.getDrawable(getResources(),R.drawable.wen, null);
drawable.setBounds(0, 0, drawable.getMinimumWidth(),
drawable.getMinimumHeight());
tv.setCompoundDrawables(drawable, null, null, null);
mmBs
  • 8,421
  • 6
  • 38
  • 46
許維德
  • 117
  • 1
  • 9
4

In Kotlin:

1) Set drawable:

val drawable = ContextCompat.getDrawable(context!!,R.drawable.ic_image)?.apply {
    setBounds(0, 0, intrinsicWidth, intrinsicHeight)
}

or

val drawable = ResourcesCompat.getDrawable(resources, R.drawable.ic_image, null)?.apply {
    setBounds(0, 0, minimumWidth, minimumHeight)
}

2) Set TextView:

textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)

or

button.setCompoundDrawables(null, drawable, null, null)
CoolMind
  • 26,736
  • 15
  • 188
  • 224
3

For me setCompoundDrawablesWithIntrinsicBounds(Drawable, Drawable, Drawable, Drawable) did not work.

I had to use setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0).

Bharat Dodeja
  • 1,137
  • 16
  • 22
2

Example with Kotlin:

    val myView = layoutInflater.inflate(R.layout.my_view, null) as TextView
    myView.setCompoundDrawablesWithIntrinsicBounds(0, myDrawable, 0, 0)
mike.tihonchik
  • 6,855
  • 3
  • 32
  • 47
1

In Kotlin with Databinding

binding.tvTime.setCompoundDrawablesWithIntrinsicBounds(
            ResourcesCompat.getDrawable(resources, android.R.drawable.ic_menu_recent_history, null),
            null,null,null)

where tvTime is textView and Position (Rigth,Top,Left,Bottom), More about binding is here https://stackoverflow.com/a/72360048/12272687

Mori
  • 2,653
  • 18
  • 24