354

I have a textView in xml here.

<TextView
        android:id="@+id/bookTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:drawableLeft="@drawable/checkmark"
        android:gravity="center_vertical"
        android:textStyle="bold"
        android:textSize="24dip"
        android:maxLines="1"
        android:ellipsize="end"/>

As you can see I set the DrawableLeft in xml.

I would like to change the drawable in code.

Is there anyway to go about doing this? Or setting the drawableLeft in code for the text view?

Cœur
  • 37,241
  • 25
  • 195
  • 267
coder_For_Life22
  • 26,645
  • 20
  • 86
  • 118

9 Answers9

958

You can use setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom)

set 0 where you don't want images

Example for Drawable on the left:

TextView textView = (TextView) findViewById(R.id.myTxtView);
textView.setCompoundDrawablesWithIntrinsicBounds(R.drawable.icon, 0, 0, 0);

Alternatively, you can use setCompoundDrawablesRelativeWithIntrinsicBounds to respect RTL/LTR layouts.


Tip: Whenever you know any XML attribute but don't have clue about how to use it at runtime. just go to the description of that property in developer doc. There you will find Related Methods if it's supported at runtime . i.e. For DrawableLeft

Andrew Orobator
  • 7,978
  • 3
  • 36
  • 36
BrainCrash
  • 12,992
  • 3
  • 32
  • 38
  • So where do i set the drawable at in this method? – coder_For_Life22 Aug 03 '11 at 20:05
  • 2
    +1 Its working for setting android:drawableLeft for TextView programatically. Thanx mate – Paresh Mayani Jul 30 '12 at 07:08
  • 47
    +1 for adding the tip. that should be the very first thing devs are told when using the docs – gmjordan Mar 06 '13 at 00:44
  • @BrainCrash You're right, I mistook it with the newer method which has the same name. – deathemperor Jan 09 '14 at 12:05
  • How to use direct drawable? is there any other method? i have Bitmap object, how can i set like this. @BrainCrash – Pratik Butani Feb 05 '14 at 07:53
  • mTextViewExpand.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.mipmap.ic_add_48, 0); – Ashwin H Apr 18 '18 at 09:28
  • 2
    Hello I was using this method to set the drawables, but I could not find its getter counter part. I had to check if the Compound textview has some drawable. How do I do that? Tried comparing `textview.getCompoundDrawablesRelative()[0]` with `mContext.getResources().getDrawable(R.drawable.my_drawable)` – ravi Aug 01 '18 at 12:55
  • if you want to use **Drawable** instead of drawable id you can go with `textView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);` – Mohd Qasim Nov 13 '21 at 02:20
  • what is that 0,0 means anyway? What if we want to set the drawableRight as it's from xml programatically? – gumuruh Feb 07 '22 at 14:22
20

Using Kotlin:

You can create an extension function or just use setCompoundDrawablesWithIntrinsicBounds directly.

fun TextView.leftDrawable(@DrawableRes id: Int = 0) {
   this.setCompoundDrawablesWithIntrinsicBounds(id, 0, 0, 0)
}

If you need to resize the drawable, you can use this extension function.

textView.leftDrawable(R.drawable.my_icon, R.dimen.icon_size)

fun TextView.leftDrawable(@DrawableRes id: Int = 0, @DimenRes sizeRes: Int) {
    val drawable = ContextCompat.getDrawable(context, id)
    val size = resources.getDimensionPixelSize(sizeRes)
    drawable?.setBounds(0, 0, size, size)
    this.setCompoundDrawables(drawable, null, null, null)
}

To get really fancy, create a wrapper that allows size and/or color modification.

textView.leftDrawable(R.drawable.my_icon, colorRes = R.color.white)

fun TextView.leftDrawable(@DrawableRes id: Int = 0, @DimenRes sizeRes: Int = 0, @ColorInt color: Int = 0, @ColorRes colorRes: Int = 0) {
    val drawable = drawable(id)
    if (sizeRes != 0) {
        val size = resources.getDimensionPixelSize(sizeRes)
        drawable?.setBounds(0, 0, size, size)
    }
    if (color != 0) {
        drawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
    } else if (colorRes != 0) {
        val colorInt = ContextCompat.getColor(context, colorRes)
        drawable?.setColorFilter(colorInt, PorterDuff.Mode.SRC_ATOP)
    }
    this.setCompoundDrawables(drawable, null, null, null)
}
Gibolt
  • 42,564
  • 15
  • 187
  • 127
17

From here I see the method setCompoundDrawablesWithIntrinsicBounds(int,int,int,int) can be used to do this.

Jack
  • 9,156
  • 4
  • 50
  • 75
8

You can use any of the following methods for setting the Drawable on TextView:

1- setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)

2- setCompoundDrawables(Left_Drawable, Top_Drawable, Right_Drawable, Bottom_Drawable)

And to get drawable from resources you can use:

getResources().getDrawable(R.drawable.your_drawable_id);
Shajeel Afzal
  • 5,913
  • 6
  • 43
  • 70
4

A Kotlin extension + some padding around the drawable

fun TextView.addLeftDrawable(drawable: Int, padding: Int = 32) {
    val imgDrawable = ContextCompat.getDrawable(context, drawable)
    compoundDrawablePadding = padding
    setCompoundDrawablesWithIntrinsicBounds(imgDrawable, null, null, null)
}
Kamal
  • 44
  • 6
r3dm4n
  • 1,175
  • 2
  • 18
  • 33
  • 1
    Slightly different solution: `fun TextView.setDrawables(@DrawableRes start: Int = 0, @DrawableRes top: Int = 0, @DrawableRes end: Int = 0, @DrawableRes bottom: Int = 0) { setCompoundDrawablesRelativeWithIntrinsicBounds(start, top, end, bottom) }` – kitfist0 May 15 '23 at 18:40
2

there are two ways of doing it either you can use XML or Java for it. If it's static and requires no changes then you can initialize in XML.

  android:drawableLeft="@drawable/cloud_up"
    android:drawablePadding="5sp"

Now if you need to change the icons dynamically then you can do it by calling the icons based on the events

       textViewContext.setText("File Uploaded");
textViewContext.setCompoundDrawablesWithIntrinsicBounds(R.drawable.uploaded, 0, 0, 0);
1

Works for me to change the text view left/right drawable color

for (drawable in binding.tvBloodPressure.compoundDrawablesRelative) {
            if (drawable != null) {
                drawable.colorFilter = PorterDuffColorFilter(
                    ContextCompat.getColor(binding.tvBloodPressure.context, color),
                    PorterDuff.Mode.SRC_IN
                )
            }
        }
0

I am using like this.

  txtUserName.setCompoundDrawablesWithIntrinsicBounds(
        requireActivity().getDrawable(
            R.drawable.ic_my_account
        ), null, null, null
    )
Peter
  • 587
  • 6
  • 16
-8
static private Drawable **scaleDrawable**(Drawable drawable, int width, int height) {

    int wi = drawable.getIntrinsicWidth();
    int hi = drawable.getIntrinsicHeight();
    int dimDiff = Math.abs(wi - width) - Math.abs(hi - height);
    float scale = (dimDiff > 0) ? width / (float)wi : height /
            (float)hi;
    Rect bounds = new Rect(0, 0, (int)(scale * wi), (int)(scale * hi));
    drawable.setBounds(bounds);
    return drawable;
}
NaviRamyle
  • 3,967
  • 1
  • 31
  • 49