Jak programowo ustawić drawableLeft na przycisku Androida?

442

Dynamicznie tworzę przyciski. Najpierw nadałem im styl XML i staram się wziąć XML poniżej i uczynić go programatycznym.

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

To właśnie mam. Mogę zrobić wszystko oprócz tego, co jest możliwe.

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
źródło

Odpowiedzi:

1054

Możesz to zrobić za pomocą setCompoundDrawablesmetody. Zobacz przykład tutaj . Użyłem tego bez użycia setBoundsi zadziałało. Możesz spróbować w jakikolwiek sposób.

AKTUALIZACJA : Skopiowanie kodu w tym przypadku powoduje uszkodzenie łącza

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

lub

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

lub

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Varun
źródło
@Varun, @Tigger: Mam z tym problem: mój menedżer plików pokazuje foldery w widoku listy z widokami tekstu i ikoną folderu jako drawableLeft. Wypróbowałem tutaj Twoje sugestie, aby ustawić „zabronioną ikonę” po kliknięciu folderu bez uprawnień do odczytu i działa. Jednak po zmianie folderów i ponownym załadowaniu adaptera ikona zabroniona pozostaje wyświetlana (tzn. Nie jest drawableLeftprzerysowana). Czy wiesz, jak ubiegać się notifyDataSetChangedo to drawableLeftbez robienia pętli? Dzięki!
Luis A. Florit,
@ LuisA.Florit Wygląda na to, że masz pytanie związane z przerysowaniem Listviewelementu, gdy zmieniają się dane - co tak naprawdę nie ma związku z tym pytaniem lub odpowiedzią. Sugeruję, abyś zamieścił pytanie zamiast komentarza.
Tigger,
@Tigger: Cóż, cofnąłem ikonę, używając twojej sztuczki, i pętli nad zabronionymi katalogami. Może to lepsze niż przerysowywanie wszystkich elementów ListView ... W każdym razie dzięki!
Luis A. Florit,
3
W mojej aplikacji widzę coś dziwnego. setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.money, 0 )Nie działa, jeśli zdefiniować drawableRight w layout.xml. Jeśli ustawię oryginalną ikonę w środku onCreate(), zmiana zadziała. Czy może to być związane z API 19?
wtryskiwacz
Przykładowy link się nie otwiera. Czy jest jakiś alternatywny link?
Yogesh Umesh Vaity
100

Po prostu możesz tego spróbować

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Jignesh Ansodariya
źródło
4
R.drawable.smiley powinien znajdować się w miejscu pierwszego 0 (pierwszego parametru), a nie ostatniego, ponieważ definicja tej metody to: {public void setCompoundDrawablesWithIntrinsicBounds (int left, int top, int right, int bottom)}
arniotaki
Jak mogę dodać do tego dopełnienie? W ten sposób nie ma zbyt wiele wypełnienia między rysunkiem a tekstem.
AdamMc331,
16

Kotlin Version

Użyj poniższego fragmentu, aby dodać lewy przycisk do rysowania:

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

.

Important Point in Using Android Vector Drawable

Jeśli używasz rysowanego wektora androida i chcesz mieć kompatybilność wsteczną dla API poniżej 21 , dodaj następujące kody do:

Na poziomie aplikacji build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

W klasie aplikacji:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}
aminografia
źródło
Prostszy sposób, który również działa dla mnie: button.setCompoundDrawablesWithIntrinsicBounds (getDrawable (R.drawable.ic_favorite_white_16dp), null, null, null)
czerwiec
2
Masz rację, ale Context#.getDrawable(resId)jest przestarzała, więc korzystanie z niej może powodować pewne problemy.
aminografia,
Działa bez dodawania w klasie aplikacji, ponieważ jej nie mam.
Mark Delphi
15

Dla mnie zadziałało:

button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);
swapnil saha
źródło
13
myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
gnganpath
źródło
4

Ja to zrobiłem:

 // 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);
użytkownik1564762
źródło
4

Jeśli używasz drawableStart , drawableEnd , drawableTop lub drawableBottom ; musisz użyć „ setCompoundDrawablesRelativeWithIntrinsicBounds

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)
Zmierzyć
źródło
3

Pracował dla mnie. Aby ustawić rysowanie po prawej stronie

tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)
Shaon
źródło
2

jak wskazał @ Jérémy Reynaud, jak opisano w tej odpowiedzi , najbezpieczniejszym sposobem ustawienia lewej wysuwalnej bez zmiany wartości innych drawable (górna, prawa i dolna) jest użycie poprzednich wartości z przycisku z 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]);

Tak więc wszystkie poprzednie rysunki zostaną zachowane.

ישו אוהב אותך
źródło
2

Poniżej przedstawiono sposób zmiany koloru lewej ikony w tekście edycji i ustawienia jej po lewej stronie.

 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
źródło
1

Może być pomocny:

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
źródło
1

Dodaj rozszerzenie Kotlin

Jeśli zamierzasz to robić często, dodanie rozszerzenia sprawia, że ​​kod jest bardziej czytelny. Przycisk rozszerza TextView; użyj przycisku, jeśli chcesz być bardziej wąski.

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

Aby skorzystać z rozszerzenia, wystarczy zadzwonić

view.leftDrawable(R.drawable.my_drawable)

Za każdym razem, gdy trzeba wyczyścić, nie należy przekazywać parametrów ani wykonywać innych połączeń o nazwie removeDrawables

Gibolt
źródło
0

Spróbuj tego:

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
źródło
-8

Spróbuj tego:

((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);
użytkownik2969017
źródło
myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); działa
Debasish Ghosh