How to programmatically set drawableLeft on Android button?

JavaAndroidAndroid LayoutAndroid 2.2-Froyo

Java Problem Overview


I'm dynamically creating buttons. I styled them using XML first, and I'm trying to take the XML below and make it programattic.

<Button
    android:id="@+id/buttonIdDoesntMatter"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:text="buttonName"
    android:drawableLeft="@drawable/imageWillChange"
    android:onClick="listener"
    android:layout_width="fill_parent">
</Button>

This is what I have so far. I can do everything but the drawable.

linear = (LinearLayout) findViewById(R.id.LinearView);
Button button = new Button(this);
button.setText("Button");
button.setOnClickListener(listener);
button.setLayoutParams(
    new LayoutParams(
	    android.view.ViewGroup.LayoutParams.FILL_PARENT,         
        android.view.ViewGroup.LayoutParams.WRAP_CONTENT
	)
);		
		
linear.addView(button);
	

Java Solutions


Solution 1 - Java

You can use the setCompoundDrawables method to do this. See the example here. I used this without using the setBounds and it worked. You can try either way.

UPDATE: Copying the code here incase the link goes down

Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
img.setBounds(0, 0, 60, 60);
txtVw.setCompoundDrawables(img, null, null, null);

or

Drawable img = getContext().getResources().getDrawable(R.drawable.smiley);
txtVw.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null);

or

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

Solution 2 - Java

Simply you can try this also

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

Solution 3 - Java

Kotlin Version

Use below snippet to add a drawable left to the button:

val drawable = ContextCompat.getDrawable(context, R.drawable.ic_favorite_white_16dp)
button.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null)

.

Important Point in Using Android Vector Drawable

When you are using an android vector drawable and want to have backward compatibility for API below 21, add the following codes to:

In app level build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

In Application class:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}

Solution 4 - Java

myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);

Solution 5 - Java

For me, it worked:

button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);

Solution 6 - Java

If you are using drawableStart, drawableEnd, drawableTop or drawableBottom; you must use "setCompoundDrawablesRelativeWithIntrinsicBounds"

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)

Solution 7 - Java

Worked for me. To set drawable at the right

tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)

Solution 8 - Java

I did this:

 // Left, top, right, bottom drawables.
            Drawable[] drawables = button.getCompoundDrawables();
            // get left drawable.
            Drawable leftCompoundDrawable = drawables[0];
            // get new drawable.
            Drawable img = getContext().getResources().getDrawable(R.drawable.ic_launcher);
            // set image size (don't change the size values)
            img.setBounds(leftCompoundDrawable.getBounds());
            // set new drawable
            button.setCompoundDrawables(img, null, null, null);

Solution 9 - Java

as @Jérémy Reynaud pointing out, as described in this [answer][1], the safest way to set the left drawable without changing the values of the other drawables (top, right, and bottom) is by using the previous values from the button with [setCompoundDrawablesWithIntrinsicBounds][2]:

Drawable leftDrawable = getContext().getResources()
                          .getDrawable(R.drawable.yourdrawable);

// Or use ContextCompat
// Drawable leftDrawable = ContextCompat.getDrawable(getContext(),
//                                        R.drawable.yourdrawable);

Drawable[] drawables = button.getCompoundDrawables();
button.setCompoundDrawablesWithIntrinsicBounds(leftDrawable,drawables[1],
                                               drawables[2], drawables[3]);

So all your previous drawable will be preserved. [1]: http://stackoverflow.com/a/18279169/43051 [2]: https://developer.android.com/reference/android/widget/TextView.html#setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable,%20android.graphics.drawable.Drawable)

Solution 10 - Java

Might be helpful:

TextView location;
location=(TextView)view.findViewById(R.id.complain_location);
//in parameter (left,top,right,bottom) any where you wnat to put
location.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.arrow,0);

Solution 11 - Java

Add a Kotlin Extension

If you are going to be doing this frequently, adding an extension makes your code more readable. Button extends TextView; use Button if you want to be more narrow.

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

To use the extension, simply call

view.leftDrawable(R.drawable.my_drawable)

Anytime you need to clear, don't pass a param or make another extension called removeDrawables

Solution 12 - Java

Following is the way to change the color of the left icon in edit text and set it in left side.

 Drawable img = getResources().getDrawable( R.drawable.user );
img.setBounds( 0, 0, 60, 60 );
mNameEditText.setCompoundDrawables(img,null, null, null);

int color = ContextCompat.getColor(this, R.color.blackColor);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    DrawableCompat.setTint(img, color);

} else {
    img.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}

Solution 13 - Java

Try this:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
     fillButton[i].setBackground(getBaseContext().getResources().getDrawable(R.drawable.drawable_name));
}
else {
    fillButton[i].setBackgroundColor(Color.argb(255,193,234,203));
}

Solution 14 - Java

Try this:

((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser375566View Question on Stackoverflow
Solution 1 - JavaVarunView Answer on Stackoverflow
Solution 2 - JavaJignesh AnsodariyaView Answer on Stackoverflow
Solution 3 - JavaaminographyView Answer on Stackoverflow
Solution 4 - JavagnganapathView Answer on Stackoverflow
Solution 5 - Javaswapnil sahaView Answer on Stackoverflow
Solution 6 - JavaMeteView Answer on Stackoverflow
Solution 7 - JavaShaonView Answer on Stackoverflow
Solution 8 - Javauser1564762View Answer on Stackoverflow
Solution 9 - Javaישו אוהב אותךView Answer on Stackoverflow
Solution 10 - JavaMuhaiminur RahmanView Answer on Stackoverflow
Solution 11 - JavaGiboltView Answer on Stackoverflow
Solution 12 - JavaRajneesh ShuklaView Answer on Stackoverflow
Solution 13 - JavaMaifee Ul AsadView Answer on Stackoverflow
Solution 14 - Javauser2969017View Answer on Stackoverflow