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


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.