Ustaw programowo kolor kształtu Androida


168

Edytuję, aby uprościć pytanie, mając nadzieję, że pomoże to w uzyskaniu dokładnej odpowiedzi.

Powiedz, że mam następujący ovalkształt:

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

Jak programowo ustawić kolor z poziomu klasy aktywności?


Do czego ustawiasz to rysowanie?
Vikram,

Drawable to ovali jest tłem ImageView.
Cote Mounyo

Jeśli to zadane pytanie jest zbyt trudne, czy istnieje sposób na narysowanie wielu obrazów na płótnie i ustawienie warstwowego produktu końcowego jako tła widoku?
Cote Mounyo

Możesz to osiągnąć, rozszerzając Viewklasę i używając jej jako basewidoku w układzie, który umożliwia nakładanie się widżetów ( RelativeLayout, FrameLayout). W tej rozszerzonej Viewklasie możesz draw multiple images onto a canvas. Ale zanim to zrobisz, spójrz na to -> Link (jeśli jeszcze tego nie zrobiłeś).
Vikram

Odpowiedzi:


266

Uwaga : odpowiedź została zaktualizowana, aby uwzględnić scenariusz, w którym backgroundwystępuje wystąpienie ColorDrawable. Dzięki Tyler Pfaff za wskazanie tego.

To, co można rysować, jest owalem i stanowi tło ImageView

Uzyskać Drawablez imageViewużyciem getBackground():

Drawable background = imageView.getBackground();

Sprawdź przeciwko zwykłym podejrzanym:

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

Wersja kompaktowa:

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

Należy pamiętać, że sprawdzanie wartości null nie jest wymagane.

Jednak powinieneś użyć mutate()na drawables przed ich modyfikacją, jeśli są używane gdzie indziej. (Domyślnie elementy rysunkowe ładowane z XML mają ten sam stan).


3
Dzięki za odpowiedź. (+1). W moim kodzie występują inne błędy, więc trudno go przetestować. Ale nadal może to ustawić solidczęść kształtu. A co z strokeporcją?
Cote Mounyo

1
@TiGer Powinieneś dodać @usernameswój komentarz, aby upewnić się, że powiadomienie zostanie wysłane do użytkownika. Nawiasem mówiąc, będziesz musiał przejść podklasę ShapeDrawable, aby ustawić część obrysu. Więcej informacji tutaj: Link . Spójrz na komentarz, ponieważ wspomina o problemie z zaakceptowaną odpowiedzią.
Vikram

3
android.graphics.drawable.GradientDrawable nie może być rzutowany na android.graphics.drawable.ShapeDrawable Rzutowanie się nie powiedzie
John

3
@John Jeśli Twoje ImageView'stło jest ustawione na a GradientDrawable, getBackground()nie zwróci a ShapeDrawable. Zamiast tego należy użyć GradientDrawable, który jest zwracany: GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();.... gradientDrawable.setColors(new int[] { color1, color2 });.
Vikram

2
Dzięki ... ocalił mój świat.
sid_09

43

Rób jak to:

    ImageView imgIcon = findViewById(R.id.imgIcon);
    GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground();
    backgroundGradient.setColor(getResources().getColor(R.color.yellow));

1
@ user3111850 Czy dodałeś android:backgroundswój plik XML, a nawet setBackgroundaktywność, zanim zadzwoniłeś getBackground()? Powinno działać, gdybyś to zrobił.
Lee Yi Hong

41

W dzisiejszych czasach prostszym rozwiązaniem byłoby użycie kształtu jako tła, a następnie programowa zmiana jego koloru poprzez:

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

Aby zapoznać się z dostępnymi opcjami, zobacz PorterDuff.Mode .

AKTUALIZACJA (API 29):

Powyższa metoda jest przestarzała od API 29 i zastąpiona następującą:

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

Aby zapoznać się z dostępnymi opcjami, zobacz BlendMode .


4
Prawidłowy to: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);ponieważ w tle może znajdować się obramowanie lub zaokrąglone pola.
Berkay Turancı,

1
Niezły @ BerkayTurancı mój kształt miał zaokrąglone rogi. Mógłbym pominąć getBackground()połączenie. Mój imageview.src zawierał kształt i użyłem: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);gdzie toggleColorjest po prostu int, który poprzednio przechował wynik z getColor ()
Someone Somewhere

1
Posiadanie PorterDuff.Modefor BlendModeColorFilternie kompiluje się tak, jak tego wymaga BlendMode. Więc dla API 29 powinno być view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Onik

Dobry chwyt @Onik. Odpowiednio zaktualizowałem odpowiedź. Dziękuję Ci!
Georgios

14

Spróbuj tego:

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

Więcej szczegółów sprawdź ten link to

mam nadzieję, że pomoże.


zagłosuj na link. Ale to nie jest odpowiedź na moje pytanie.
Cote Mounyo

13

mam nadzieję, że to pomoże komuś z tym samym problemem

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
Początkowo nie mogłem tego uruchomić, pomyślałem, że twój kolor musi być podany w następujący sposób:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

Rozszerzając odpowiedź Vikrama , jeśli kolorujesz dynamiczne widoki, takie jak elementy widoku recyklera, itp. .... Wtedy prawdopodobnie będziesz chciał wywołać mutate () przed ustawieniem koloru. Jeśli tego nie zrobisz, wszystkie widoki, które mają wspólny element do rysowania (tj. Tło), również zostaną zmienione / pokolorowane.

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
potrzeby i dodatkowe sprawdzenie i parametr: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]aby poradzić sobie z układami tła, które używają <layer-list ... <item ....
Johny

11

Na to pytanie odpowiedziano jakiś czas temu, ale można je zmodernizować, przepisując jako funkcję rozszerzenia kotlin.

fun Drawable.overrideColor(@ColorInt colorInt: Int) {
    when (this) {
        is GradientDrawable -> setColor(colorInt)
        is ShapeDrawable -> paint.color = colorInt
        is ColorDrawable -> color = colorInt
    }
}

7

to jest rozwiązanie, które u mnie działa ... napisałam też w innym pytaniu: Jak dynamicznie zmieniać kształt kolorystyczny?

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

Nic nie działa dla mnie, ale kiedy ustawię odcień, działa to na Shape Drawable

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

wymaga Android 5.0 API 21


3

Moja wersja funkcji rozszerzenia Kotlin oparta na odpowiedziach powyżej z 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

Prosty sposób wypełnienia kształtu promieniem to:

(view.getBackground()).setColorFilter(Color.parseColor("#FFDE03"), PorterDuff.Mode.SRC_IN);

1

Może jestem za późno, ale jeśli używasz Kotlina. Jest taki sposób

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)

Cieszyć się....


0

Dla każdego, kto używa języka C # Xamarin, oto metoda oparta na fragmencie Vikrama:

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;
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.