Come impostare programmabilmente drawableLeft sul pulsante Android?


442

Sto creando dinamicamente pulsanti. Li ho disegnati prima usando XML, e sto provando a prendere l'XML qui sotto e renderlo programmatico.

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

Questo è quello che ho finora. Posso fare tutto tranne il disegnabile.

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

Risposte:


1055

È possibile utilizzare il setCompoundDrawablesmetodo per farlo. Vedi l'esempio qui . L'ho usato senza usare setBoundse ha funzionato. Puoi provare in entrambi i modi.

AGGIORNAMENTO : Copiando qui il codice in caso di collegamento inattivo

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: Ho un problema con questo: Il mio file manager mostra le cartelle in una lista con visualizzazioni di testo e un'icona di cartella come drawableLeft. Ho provato i tuoi suggerimenti qui per impostare un'icona vietata quando fai clic in una cartella senza autorizzazioni di lettura e funziona. Tuttavia, quando si cambiano le cartelle e l'adattatore viene ricaricato, l'icona proibita persiste (ovvero drawableLeftnon viene ridisegnata). Sai fare domanda notifyDataSetChangedanche per drawableLeft, senza fare un ciclo? Grazie!
Luis A. Florit,

@ LuisA.Florit Sembra che tu abbia una domanda relativa al ridisegno di un Listviewelemento quando i dati cambiano, il che non si riferisce realmente a questa domanda o risposta. Ti suggerisco di pubblicare una domanda anziché un commento.
Tigro,

@Tigger: Bene, ho ripristinato l'icona usando anche il tuo trucco, e un ciclo sopra le directory proibite. Forse è meglio che ridisegnare tutti gli elementi di ListView ... Grazie comunque!
Luis A. Florit,

3
Vedo qualcosa di strano nella mia app. Il setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.money, 0 )non funziona, se io definisco il drawableRight nel layout.xml. Se imposto l'icona originale all'interno onCreate(), la modifica funziona. Potrebbe essere correlato all'API 19?
injecteer,

Il link di esempio non si apre. C'è qualche link alternativo?
Yogesh Umesh Vaity,

100

Puoi semplicemente provare anche questo

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

4
R.drawable.smiley dovrebbe essere al posto del primo 0 (il primo parametro) non l'ultimo perché la definizione di questo metodo è: {public void setCompoundDrawablesWithIntrinsicBounds (int left, int top, int right, int bottom)}
arniotaki

Come posso aggiungere anche l'imbottitura? Non c'è molta imbottitura tra il disegno e il testo in questo modo.
AdamMc331,

16

Kotlin Version

Usa lo snippet di seguito per aggiungere un disegno a sinistra al pulsante:

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

.

Important Point in Using Android Vector Drawable

Quando si utilizza un disegno vettoriale Android e si desidera avere una compatibilità con le versioni precedenti per API inferiore a 21 , aggiungere i seguenti codici a:

A livello di app build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

Nella classe di applicazione:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}

Un modo più semplice che funziona anche per me: button.setCompoundDrawablesWithIntrinsicBounds (getDrawable (R.drawable.ic_favorite_white_16dp), null, null, null)
juangalf

2
Hai ragione, ma Context#.getDrawable(resId)è deprecato, quindi l'utilizzo potrebbe causare alcuni problemi.
aminografia,

Funziona senza aggiungere in classe Application poiché non ne ho uno.
Mark Delphi,

15

Per me ha funzionato:

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

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

4

L'ho fatto:

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

Se si utilizza drawableStart , drawableEnd , drawableTop o drawableBottom ; devi usare " setCompoundDrawablesRelativeWithIntrinsicBounds "

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

3

Ha funzionato per me. Per impostare il disegno a destra

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

2

come @ Jérémy Reynaud sottolineando, come descritto in questa risposta , il modo più sicuro per impostare il drawable sinistro senza cambiare i valori degli altri drawable (in alto, a destra e in basso) è usando i valori precedenti dal pulsante 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]);

Quindi tutti i tuoi disegni precedenti verranno conservati.


2

Di seguito è riportato il modo per cambiare il colore dell'icona sinistra nel testo di modifica e impostarlo sul lato sinistro.

 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

Potrebbe essere utile:

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

Aggiungi un'estensione Kotlin

Se lo farai frequentemente, l'aggiunta di un'estensione rende il tuo codice più leggibile. Il pulsante estende TextView; usa il pulsante se vuoi essere più stretto.

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

Per utilizzare l'estensione, è sufficiente chiamare

view.leftDrawable(R.drawable.my_drawable)

Ogni volta che è necessario cancellare, non passare un parametro o fare un altro interno chiamato removeDrawables


0

Prova questo:

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

Prova questo:

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

myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); funziona
Debasish Ghosh,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.