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

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, @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);

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

}

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

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

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

4

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

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

3

Trabajó para mi. Para establecer dibujable a la derecha

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

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.


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

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

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


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

-8

Prueba esto:

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

myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); funciona
— Debasish Ghosh
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.