Comment définir par programme drawableLeft sur le bouton Android?

442

Je crée dynamiquement des boutons. Je les ai d'abord stylisés en utilisant XML, et j'essaie de prendre le XML ci-dessous et de le rendre programmatique.

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

C'est ce que j'ai jusqu'à présent. Je peux tout faire sauf le tirable.

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

Réponses:

1055

Vous pouvez utiliser la setCompoundDrawablesméthode pour ce faire. Voir l'exemple ici . Je l'ai utilisé sans utiliser le setBoundset cela a fonctionné. Vous pouvez essayer de toute façon.

MISE À JOUR : Copier le code ici au cas où le lien descend

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

ou

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

ou

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Varun
la source
@Varun, @Tigger: J'ai un problème avec ceci: mon gestionnaire de fichiers affiche les dossiers dans une liste avec des vues de texte et une icône de dossier en tant que drawableLeft. J'ai essayé vos suggestions ici pour définir une "icône interdite" lorsque vous cliquez dans un dossier sans autorisations de lecture, et cela fonctionne. Toutefois, lorsque vous changez de dossier et que l'adaptateur est rechargé, l'icône interdite persiste (c'est-à-dire qu'elle n'est drawableLeftpas redessinée). Savez-vous comment postuler notifyDataSetChangedaussi pour le drawableLeft, sans faire de boucle? Merci!
Luis A. Florit
@ LuisA.Florit Il semble que vous ayez une question liée au redessin d'un Listviewélément lorsque les données changent - ce qui n'a pas vraiment de rapport avec cette question ou réponse. Je vous suggère de poster une question au lieu d'un commentaire.
Tigger
@Tigger: Eh bien, j'ai également rétabli l'icône en utilisant votre astuce et une boucle sur les répertoires interdits. Peut-être que c'est mieux que de redessiner tous les éléments ListView ... Merci quand même!
Luis A. Florit
3
Je vois quelque chose d'étrange dans mon application. Le setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.money, 0 )ne fonctionne pas, si je définis le drawableRight dans le layout.xml. Si je mets l'icône d'origine à l'intérieur onCreate(), le changement fonctionne. Pourrait-il être lié à l'API 19?
injecteur
L'exemple de lien ne s'ouvre pas. Existe-t-il un lien alternatif?
Yogesh Umesh Vaity
100

Vous pouvez aussi l'essayer aussi

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Jignesh Ansodariya
la source
4
R.drawable.smiley devrait être à la place du premier 0 (le premier paramètre) et non du dernier car la définition de cette méthode est: {public void setCompoundDrawablesWithIntrinsicBounds (int gauche, int haut, int droite, int bas)}
arniotaki
Comment puis-je également ajouter un rembourrage autour de cela? Il n'y a pas beaucoup de remplissage entre le dessinable et le texte de cette façon.
AdamMc331
16

Kotlin Version

Utilisez l'extrait ci-dessous pour ajouter une gauche dessinable au bouton:

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

.

Important Point in Using Android Vector Drawable

Lorsque vous utilisez un vecteur Android dessinable et que vous souhaitez avoir une compatibilité descendante pour l' API inférieure à 21 , ajoutez les codes suivants à:

Au niveau de l'application build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

Dans la classe Application:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}
aminographie
la source
Une manière plus simple qui fonctionne aussi pour moi: button.setCompoundDrawablesWithIntrinsicBounds (getDrawable (R.drawable.ic_favorite_white_16dp), null, null, null)
juangalf
2
Vous avez raison, mais vous êtes Context#.getDrawable(resId)déconseillé, son utilisation peut donc entraîner des problèmes.
aminographie
Fonctionne sans ajouter de classe Application car je n'en ai pas.
Mark Delphi
15

Pour moi, cela a fonctionné:

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

J'ai fait ça:

 // 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);
user1564762
la source
4

Si vous utilisez drawableStart , drawableEnd , drawableTop ou drawableBottom ; vous devez utiliser " setCompoundDrawablesRelativeWithIntrinsicBounds "

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)
Infliger
la source
3

A travaillé pour moi. Pour régler le dessin à droite

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

comme le souligne @ Jérémy Reynaud, comme décrit dans cette réponse , le moyen le plus sûr de définir le dessin à gauche sans modifier les valeurs des autres dessinables (en haut, à droite et en bas) consiste à utiliser les valeurs précédentes du bouton avec 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]);

Ainsi, tous vos tirables précédents seront conservés.

ישו אוהב אותך
la source
2

Voici la façon de changer la couleur de l'icône de gauche dans le texte d'édition et de la définir dans le côté gauche.

 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
la source
1

Pourrait être 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);
Muhaiminur Rahman
la source
1

Ajouter une extension Kotlin

Si vous comptez le faire fréquemment, l'ajout d'une extension rend votre code plus lisible. Le bouton étend TextView; utilisez Button si vous voulez être plus étroit.

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

Pour utiliser l'extension, appelez simplement

view.leftDrawable(R.drawable.my_drawable)

Chaque fois que vous devez effacer, ne passez pas un paramètre ou ne créez pas une autre extension appelée removeDrawables

Gibolt
la source
0

Essaye ça:

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
la source
-8

Essaye ça:

((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);
user2969017
la source
myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); travaux
Debasish Ghosh