Задайте андроїд колір форми програмно


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>

Як встановити колір програмно, з класу діяльності?


Для чого ви це налаштовано?
Вікрам

Малюнок є ovalі є фоном ImageView.
Cote Mounyo,

Якщо це запитання, як задається, занадто складне, чи є спосіб намалювати на полотні кілька зображень і встановити шаруватий кінцевий продукт як фон перегляду?
Cote Mounyo

Цього можна досягти, розширивши Viewклас і використовуючи його як baseперегляд у макеті, що дозволяє перекривати віджети ( RelativeLayout, FrameLayout). Всередині цього розширеного Viewкласу ви можете draw multiple images onto a canvas. Але, перш ніж це зробити, погляньте на це -> Посилання (якщо ви ще цього не зробили).
Вікрам

Відповіді:


266

Примітка : Відповідь було оновлено, щоб охопити сценарій, де backgroundє примірник ColorDrawable. Дякую Тайлеру Пфаффу , що вказав на це.

Малюнок є овальним і є фоном 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порції?
Cote Mounyo

1
@TiGer Ви повинні додати @usernameсвій коментар, щоб переконатися, що повідомлення надсилається користувачеві. До речі, вам потрібно буде підклас ShapeDrawable, щоб встановити частину обведення. Більше інформації тут: Посилання . Подивіться на коментар, оскільки в ньому згадується проблема із прийнятою відповіддю.
Вікрам

3
android.graphics.drawable.GradientDravable не можна передавати на android.graphics.dravable.ShapeDravable Литий збій на мене
Джон

3
@John Якщо для вашого ImageView'sфону встановлено значення a GradientDrawable, getBackground()не повернеться 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));

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);Оскільки на задньому плані може бути рамка або округлі курсори.
Беркай Туранчі

1
Хороший @ BerkayTurancı у моєї форми був закруглені кути. Я міг опустити getBackground()дзвінок. Мій imageview.src містив форму, і я використав: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);де toggleColorлише int, який раніше зберігав результат від getColor ()
Хтось десь

1
Маючи PorterDuff.Modeза BlendModeColorFilterНЕ скомпілюється , оскільки вона вимагає BlendMode. Тож для API 29 це має бути view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Оник

Хороший улов @Onik. Відповідно я оновив відповідь. Дякую!
Георгіос

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

для більш детальної інформації перевірте це посилання це

сподіваюся на допомогу.


голосувати за посилання. Але це не відповідь на моє запитання.
Cote Mounyo,

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

1
Спочатку я не міг змусити це працювати, я зрозумів, що ваш колір повинен бути наданий таким чином:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

Розширення на відповідь Vikram , якщо ви забарвлюєте динамічні види, наприклад, елементи перегляду рециркулятора тощо. Тоді ви, ймовірно, хочете зателефонувати 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


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

1

Можливо, я занадто пізно. Але якщо ви використовуєте Котлін. Є такий спосіб

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, ось метод, заснований на фрагменті Vikram:

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;
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.