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