¿Cómo establecer programáticamente drawableLeft en el botón de Android?

442

Estoy creando dinámicamente botones. Primero los diseñé usando XML, y estoy tratando de tomar el XML a continuación y hacerlo programático.

<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>

Esto es lo que tengo hasta ahora. Puedo hacer todo menos lo dibujable.

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);
Tim
fuente

Respuestas:

1054

Puedes usar el setCompoundDrawablesmétodo para hacer esto. Vea el ejemplo aquí . Usé esto sin usar el setBoundsy funcionó. Puedes intentarlo de cualquier manera.

ACTUALIZACIÓN : copiando el código aquí en caso de que el enlace se caiga

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

o

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

o

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Varun
fuente
@Varun, @Tigger: Tengo un problema con esto: mi administrador de archivos muestra carpetas en una vista de lista con vistas de texto y un icono de carpeta como a drawableLeft. Intenté sus sugerencias aquí para establecer un "icono prohibido" cuando hace clic en una carpeta sin permisos de lectura, y funciona. Sin embargo, cuando cambia las carpetas y el adaptador se drawableLeftvuelve a cargar, el icono prohibido persiste (es decir, no se vuelve a dibujar). ¿Sabes cómo aplicar notifyDataSetChangedtambién para el drawableLeft, sin hacer un bucle? ¡Gracias!
Luis A. Florit
@ LuisA.Florit Parece que tiene una pregunta relacionada con el rediseño de un Listviewelemento cuando los datos cambian, lo que realmente no se relaciona con esta pregunta o respuesta. Le sugiero que publique una pregunta en lugar de un comentario.
Tigger
@Tigger: Bueno, volví al icono usando tu truco también, y un bucle sobre los directorios prohibidos. Tal vez esto sea mejor que volver a dibujar todos los elementos de ListView ... ¡Gracias de todos modos!
Luis A. Florit
3
Estoy viendo algo extraño en mi aplicación. El setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.money, 0 )no funciona, si defino el drawableRight en el layout.xml. Si configuro el ícono original dentro onCreate(), entonces el cambio funciona. ¿Podría estar relacionado con la API 19?
inyector
El enlace de ejemplo no se está abriendo. ¿Hay algún enlace alternativo?
Yogesh Umesh Vaity
100

Simplemente puedes probar esto también

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Jignesh Ansodariya
fuente
44
R.drawable.smiley debe estar en el lugar del primer 0 (el primer parámetro) no el último porque la definición de este método es: {public void setCompoundDrawablesWithIntrinsicBounds (int left, int top, int right, int bottom)}
arniotaki
¿Cómo puedo agregar relleno alrededor de esto también? No hay mucho relleno entre el dibujo y el texto de esta manera.
AdamMc331
16

Kotlin Version

Use el fragmento a continuación para agregar una izquierda dibujable al botón:

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

.

Important Point in Using Android Vector Drawable

Cuando esté utilizando un vector de Android dibujable y desee tener compatibilidad con versiones anteriores para API por debajo de 21 , agregue los siguientes códigos a:

En el nivel de la aplicación build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

En clase de aplicación:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}
aminografía
fuente
Una forma más simple que también funciona para mí: button.setCompoundDrawablesWithIntrinsicBounds (getDrawable (R.drawable.ic_favorite_white_16dp), null, null, null)
juangalf
2
Tienes razón, pero Context#.getDrawable(resId)está en desuso, por lo que usarlo puede causar algunos problemas.
Aminografía
Funciona sin agregar clase de aplicación ya que no tengo una.
Mark Delphi
15

Para mí funcionó:

button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);
swapnil saha
fuente
13
myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
gnganpath
fuente
4

Hice esto:

 // 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);
usuario1564762
fuente
4

Si está utilizando drawableStart , drawableEnd , drawableTop o drawableBottom ; debes usar " setCompoundDrawablesRelativeWithIntrinsicBounds "

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)
Asignar
fuente
3

Trabajó para mi. Para establecer dibujable a la derecha

tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)
Shaon
fuente
2

como señaló @ Jérémy Reynaud, como se describe en esta respuesta , la forma más segura de establecer el dibujo izquierdo sin cambiar los valores de los otros elementos dibujables (superior, derecho e inferior) es mediante el uso de los valores anteriores del botón con setCompoundDrawablesWithIntrinsicBounds :

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]);

Por lo tanto, se conservarán todos sus dibujos anteriores.

ישו אוהב אותך
fuente
2

A continuación se muestra la forma de cambiar el color del icono izquierdo en editar texto y configurarlo en el lado izquierdo.

 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);
}
Rajneesh Shukla
fuente
1

Puede ser útil:

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);
Muhaiminur Rahman
fuente
1

Agregar una extensión de Kotlin

Si va a hacer esto con frecuencia, agregar una extensión hace que su código sea más legible. El botón extiende TextView; usa el botón si quieres ser más angosto.

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

Para usar la extensión, simplemente llame

view.leftDrawable(R.drawable.my_drawable)

Cada vez que necesite borrar, no pase un parámetro ni realice otra extensión llamada removeDrawables

Gibolt
fuente
0

Prueba esto:

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));
}
Maifee Ul Asad
fuente
-8

Prueba esto:

((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);
usuario2969017
fuente
myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); funciona
Debasish Ghosh