Установить цвет формы Android программно

168

Я редактирую, чтобы сделать вопрос проще, надеясь, что это поможет найти точный ответ.

Скажем, у меня есть следующая ovalформа:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <solid android:angle="270"
           android:color="#FFFF0000"/>
    <stroke android:width="3dp"
            android:color="#FFAA0055"/>
</shape>

Как установить цвет программно, из класса занятий?

Кот Мунио
источник
Что вы устанавливаете для этого?
Викрам
Drawable является ovalи является фоном ImageView.
Кот Мунио
Если заданный вопрос слишком сложен, есть ли способ нарисовать несколько изображений на холсте и установить конечный продукт со слоями в качестве фона вида?
Кот Мунио
Вы можете достичь этого, расширяя Viewкласс и используя его в качестве baseпредставления в макете, который позволяет перекрывать виджеты ( RelativeLayout, FrameLayout). Внутри этого расширенного Viewкласса вы можете draw multiple images onto a canvas. Но, прежде чем сделать это, взгляните на это -> Ссылка (если вы еще этого не сделали).
Викрам

Ответы:

266

Примечание . Ответ был обновлен, чтобы охватить сценарий, к которому backgroundотносится экземпляр ColorDrawable. Спасибо Тайлеру Пфаффу за то, что указал на это.

Drawable является овалом и является фоном ImageView

Получить Drawableот imageViewиспользования getBackground():

Drawable background = imageView.getBackground();

Сверьтесь с обычными подозреваемыми:

if (background instanceof ShapeDrawable) {
    // cast to 'ShapeDrawable'
    ShapeDrawable shapeDrawable = (ShapeDrawable) background;
    shapeDrawable.getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    // cast to 'GradientDrawable'
    GradientDrawable gradientDrawable = (GradientDrawable) background;
    gradientDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    // alpha value may need to be set again after this call
    ColorDrawable colorDrawable = (ColorDrawable) background;
    colorDrawable.setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

Компактная версия:

Drawable background = imageView.getBackground();
if (background instanceof ShapeDrawable) {
    ((ShapeDrawable)background).getPaint().setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof GradientDrawable) {
    ((GradientDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
} else if (background instanceof ColorDrawable) {
    ((ColorDrawable)background).setColor(ContextCompat.getColor(mContext,R.color.colorToSet));
}

Обратите внимание, что нулевая проверка не требуется.

Тем не менее, вы должны использовать mutate()на чертежах перед их изменением, если они используются в другом месте. (По умолчанию загружаемые из XML файлы рисования имеют одинаковое состояние.)

Викрам
источник
3
Спасибо за ответы. (+1). Мой код испытывает другие ошибки, поэтому его сложно протестировать. Но все же это может установить solidчасть формы. Как насчет strokeпорции?
Кот Мунио
1
@TiGer Вы должны добавить @usernameсвой комментарий, чтобы убедиться, что пользователю отправлено уведомление. Кстати, вам нужно будет ShapeDrawableсоздать подкласс для того, чтобы установить часть обводки. Больше информации здесь: Ссылка . Посмотрите на комментарий, поскольку он упоминает проблему с принятым ответом.
Викрам
3
android.graphics.drawable.GradientDrawable не может быть приведен к android.graphics.drawable.ShapeDrawable Приведение мне не удалось
Джон
3
@John Если ImageView'sфон установлен на a GradientDrawable, getBackground()не вернет a ShapeDrawable. Вместо этого используйте GradientDrawable, возвращаемый: GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();.... gradientDrawable.setColors(new int[] { color1, color2 });.
Викрам
2
Спасибо .. спас мой мир.
sid_09
43

Делай так:

    ImageView imgIcon = findViewById(R.id.imgIcon);
    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
    backgroundGradient.setColor(getResources().getColor(R.color.yellow));
Leonly91
источник
1
@ user3111850 Вы добавили android:backgroundсвой xml или даже setBackgroundв активность перед звонком getBackground()? Это должно работать, если вы сделали это.
Ли И Хонг
41

В настоящее время более простым решением было бы использовать вашу форму в качестве фона, а затем программно изменить ее цвет с помощью:

view.background.setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP)

Смотрите PorterDuff.Mode для доступных опций.

ОБНОВЛЕНИЕ (API 29):

Вышеуказанный метод устарел начиная с API 29 и заменен следующим:

view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP)

См. BlendMode для доступных опций.

Георгиос
источник
4
Правильно одно: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);на фоне могут быть границы или закругленные углы.
Berkay Turancı
1
Хороший @ BerkayTurancı моя форма имела закругленные углы. Я мог бы пропустить getBackground()звонок. Мой imageview.src содержал форму, и я использовал: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);где toggleColorтолько int, который ранее сохранял результат от getColor ()
Someone Somewhere
1
Наличие PorterDuff.Modeдля BlendModeColorFilterне компилируется, как это требуется BlendMode. Так что для API 29 так и должно быть view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Оник
Хороший улов @ Оник. Я обновил ответ соответственно. Спасибо!
Георгиос
14

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

 public void setGradientColors(int bottomColor, int topColor) {
 GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[]  
 {bottomColor, topColor});
 gradient.setShape(GradientDrawable.RECTANGLE);
 gradient.setCornerRadius(10.f);
 this.setBackgroundDrawable(gradient);
 }

подробнее проверить эту ссылку это

надеюсь помочь.

androidqq6
источник
голосование за ссылку. Но это не ответ на мой вопрос.
Кот Мунио
13

надеюсь, что это поможет кому-то с той же проблемой

GradientDrawable gd = (GradientDrawable) YourImageView.getBackground();
//To shange the solid color
gd.setColor(yourColor)

//To change the stroke color
int width_px = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, youStrokeWidth, getResources().getDisplayMetrics());
gd.setStroke(width_px, yourColor);
medhdj
источник
1
Первоначально я не мог заставить это работать, я понял, что ваш Color должен быть представлен следующим образом:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce
12

Расширяя ответ Викрама , если вы раскрашиваете динамические представления, такие как элементы представления переработчика и т. Д. ... Тогда вы, вероятно, захотите вызвать mutate (), прежде чем установить цвет. Если вы этого не сделаете, любые виды, которые имеют общий объект рисования (например, фон), также будут иметь свои измененные / цветные рисунки.

public static void setBackgroundColorAndRetainShape(final int color, final Drawable background) {

    if (background instanceof ShapeDrawable) {
        ((ShapeDrawable) background.mutate()).getPaint().setColor(color);
    } else if (background instanceof GradientDrawable) {
        ((GradientDrawable) background.mutate()).setColor(color);
    } else if (background instanceof ColorDrawable) {
        ((ColorDrawable) background.mutate()).setColor(color);
    }else{
        Log.w(TAG,"Not a valid background type");
    }

}
Тайлер Пфафф
источник
3
Нужны и дополнительные проверки и параметры: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]для работы с фонами, которые используют <layer-list ... <item ....
Джонни
11

На этот вопрос был дан ответ некоторое время назад, но его можно модернизировать, переписав его как функцию расширения kotlin.

fun Drawable.overrideColor(@ColorInt colorInt: Int) {
    when (this) {
        is GradientDrawable -> setColor(colorInt)
        is ShapeDrawable -> paint.color = colorInt
        is ColorDrawable -> color = colorInt
    }
}
Карлос Паулино
источник
7

это решение, которое работает для меня ... написал также в другом вопросе: Как динамически изменить цвет формы?

//get the image button by id
ImageButton myImg = (ImageButton) findViewById(R.id.some_id);

//get drawable from image button
GradientDrawable drawable = (GradientDrawable) myImg.getDrawable();

//set color as integer
//can use Color.parseColor(color) if color is a string
drawable.setColor(color)
Сообщество
источник
4

Ничто не работает для меня, но когда я устанавливаю оттенок, он работает на Shape Drawable

 Drawable background = imageView.getBackground();
 background.setTint(getRandomColor())

требуется Android 5.0 API 21

Sumit
источник
3

Моя версия функции расширения Kotlin, основанная на ответах выше с Compat :

fun Drawable.overrideColor_Ext(context: Context, colorInt: Int) {
    val muted = this.mutate()
    when (muted) {
        is GradientDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        is ShapeDrawable -> muted.paint.setColor(ContextCompat.getColor(context, colorInt))
        is ColorDrawable -> muted.setColor(ContextCompat.getColor(context, colorInt))
        else -> Log.d("Tag", "Not a valid background type")
    }
}
Саттар Хумматли
источник
1

Простой способ заполнить форму радиусом :

(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);
SANAT
источник
1

Может быть, я слишком поздно. Но если вы используете Kotlin. Есть такой способ

var gd = layoutMain.background as GradientDrawable

 //gd.setCornerRadius(10)
  gd.setColor(ContextCompat.getColor(ctx , R.color.lightblue))
  gd.setStroke(1, ContextCompat.getColor(ctx , R.color.colorPrimary)) // (Strokewidth,colorId)

Наслаждаться....

Ревностная Система
источник
0

Для тех, кто использует C # Xamarin, вот метод, основанный на фрагменте Викрама:

private void SetDrawableColor(Drawable drawable, Android.Graphics.Color color)
{
    switch (drawable)
    {
        case ShapeDrawable sd:
            sd.Paint.Color = color;
            break;
        case GradientDrawable gd:
            gd.SetColor(color);
            break;
        case ColorDrawable cd:
            cd.Color = color;
            break;
    }
}
Райан
источник