Как программно установить drawableLeft на кнопку Android?

442

Я динамически создаю кнопки. Сначала я их стилизовал, используя XML, и я пытаюсь взять XML ниже и сделать его программным.

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

Это то, что я до сих пор. Я могу сделать все, кроме рисования.

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);
Тим
источник

Ответы:

1055

Вы можете использовать setCompoundDrawablesметод, чтобы сделать это. Смотрите пример здесь . Я использовал это без использования, setBoundsи это сработало. Вы можете попробовать в любом случае.

ОБНОВЛЕНИЕ : Копирование кода здесь, если ссылка не работает

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

или

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

или

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Варуна
источник
@Varun, @Tigger: у меня проблема с этим: мой файловый менеджер показывает папки в виде списка с текстовыми представлениями и значок папки в виде drawableLeft. Я попробовал ваши предложения здесь, чтобы установить «запрещенную иконку», когда вы нажимаете в папке без разрешений на чтение, и это работает. Однако при смене папок и перезагрузке адаптера запрещенный значок сохраняется (то есть drawableLeftне перерисовывается). Знаете ли вы, как подать заявку notifyDataSetChangedтакже drawableLeft, без выполнения цикла? Спасибо!
Луис А. Флорит
@ LuisA.Florit Похоже, у вас есть вопрос, связанный с перерисовкой Listviewэлемента при изменении данных, который на самом деле не имеет отношения к этому вопросу или ответу. Я предлагаю вам оставить вопрос вместо комментария.
Тигр
@Tigger: Ну, я вернул значок назад, используя твой трюк, и цикл по запрещенным папкам. Может быть, это лучше, чем перерисовывать все элементы ListView ... В любом случае, спасибо!
Луис А. Флорит
3
Я вижу что-то странное в моем приложении. setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.money, 0 )Не работает, если я определить drawableRight в layout.xml. Если я установлю оригинальную иконку внутри onCreate(), то изменение сработает. Может ли это быть связано с API 19?
Инжектор
Пример ссылки не открывается. Есть ли альтернативная ссылка?
Йогеш Умеш Вайты
100

Просто вы можете попробовать это также

txtVw.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
Джинеш Ансодария
источник
4
R.drawable.smiley должен стоять на месте первого 0 (первый параметр), а не последнего, потому что определение этого метода: {public void setCompoundDrawablesWithIntrinsicBounds (int left, int top, int right, int bottom)}
арниотаки
Как я могу добавить отступы вокруг этого тоже? Таким образом, между отрисовкой и текстом не так много отступов.
AdamMc331
16

Kotlin Version

Используйте фрагмент ниже, чтобы добавить левую кнопку для кнопки:

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

,

Important Point in Using Android Vector Drawable

Если вы используете векторное изображение Android и хотите иметь обратную совместимость для API ниже 21 , добавьте следующие коды:

На уровне приложения build.gradle:

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

В классе приложений:

class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()

        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
    }

}
аминография
источник
Более простой способ, который также работает для меня: button.setCompoundDrawablesWithIntrinsicBounds (getDrawable (R.drawable.ic_favorite_white_16dp), нуль,
ноль, ноль
2
Вы правы, но Context#.getDrawable(resId)не рекомендуется, поэтому его использование может вызвать некоторые проблемы.
аминография
Работает без добавления в классе приложения, так как у меня его нет.
Марк Дельфи
15

Для меня это сработало:

button.setCompoundDrawablesWithIntrinsicBounds(com.example.project1.R.drawable.ic_launcher, 0, 0, 0);
свапнил саха
источник
13
myEdtiText.setCompoundDrawablesWithIntrinsicBounds(R.drawable.smiley, 0, 0, 0);
gnganpath
источник
4

Я сделал это:

 // 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
источник
4

Если вы используете drawableStart , drawableEnd , drawableTop или drawableBottom ; Вы должны использовать " setCompoundDrawablesRelativeWithIntrinsicBounds "

edittext.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.anim_search_to_close, 0)
Мета
источник
3

Работал на меня. Чтобы установить рисование справа

tvBioLive.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close_red_400_24dp, 0)
Shaon
источник
2

как указал @ Jérémy Reynaud, как описано в этом ответе , самый безопасный способ установить левую отрисовку без изменения значений других отрисовок (верхней, правой и нижней) - использовать предыдущие значения кнопки с 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]);

Таким образом, все ваши предыдущие рисунки будут сохранены.

ישו אוהב אותך
источник
2

Ниже приведен способ изменить цвет левого значка в редактируемом тексте и установить его в левой части.

 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

Может быть полезно:

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

Добавить расширение Kotlin

Если вы собираетесь делать это часто, добавление расширения сделает ваш код более читабельным. Кнопка расширяет TextView; используйте кнопку, если вы хотите быть более узким.

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

Чтобы использовать расширение, просто позвоните

view.leftDrawable(R.drawable.my_drawable)

В любое время, когда вам нужно очистить, не передавайте параметр или сделайте другое расширение под названием removeDrawables

Gibolt
источник
0

Попробуй это:

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

Попробуй это:

((Button)btn).getCompoundDrawables()[0].setAlpha(btn.isEnabled() ? 255 : 100);
user2969017
источник
myEdtiText.setCompoundDrawablesWithIntrinsicBounds (R.drawable.smiley, 0, 0, 0); работы
Дебашиш Гош