Imposta il colore della forma Android a livello di codice


168

Sto modificando per rendere la domanda più semplice, sperando che aiuti a una risposta accurata.

Di 'che ho la seguente ovalforma:

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

Come posso impostare il colore a livello di codice, all'interno di una classe di attività?


A cosa imposti questo drawable?
Vikram,

Il disegno è un ovaled è lo sfondo di un ImageView.
Cote Mounyo,

Se questa domanda posta è troppo difficile, c'è un modo per disegnare più immagini su una tela e impostare il prodotto finale a strati come sfondo di una vista?
Cote Mounyo,

È possibile ottenere ciò estendendo la Viewclasse e utilizzandola come basevista in un layout che consente la sovrapposizione di widget ( RelativeLayout, FrameLayout). All'interno di questa Viewclasse estesa , puoi draw multiple images onto a canvas. Ma, prima di farlo, dai un'occhiata a questo -> Link (se non l'hai già fatto).
Vikram,

Risposte:


266

Nota : la risposta è stata aggiornata per coprire lo scenario in cui si backgroundtrova un'istanza di ColorDrawable. Grazie Tyler Pfaff , per averlo segnalato.

Il disegno è un ovale ed è lo sfondo di un ImageView

Ottieni Drawableda imageViewusando getBackground():

Drawable background = imageView.getBackground();

Controlla contro i soliti sospetti:

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

Versione compatta:

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

Si noti che il controllo null non è richiesto.

Tuttavia, è necessario utilizzare mutate()i disegni prima di modificarli se utilizzati altrove. (Per impostazione predefinita, i drawable caricati da XML condividono lo stesso stato.)


3
Grazie per aver risposto. (+1). Il mio codice presenta altri bug, quindi è difficile testarlo. Tuttavia, ciò potrebbe impostare la solidparte della forma. Che ne dici della strokeporzione?
Cote Mounyo,

1
@TiGer È necessario aggiungere @usernameun commento per assicurarsi che venga inviata una notifica all'utente. A proposito, dovrai ShapeDrawableimpostare una sottoclasse per impostare la parte del tratto. Maggiori informazioni qui: Link . Guarda il commento in quanto menziona un problema con la risposta accettata.
Vikram,

3
android.graphics.drawable.GradientDrawable non può essere lanciato su android.graphics.drawable.ShapeDrawable Il cast fallisce su di me
John

3
@John Se lo ImageView'ssfondo è impostato su a GradientDrawable, getBackground()non verrà restituito a ShapeDrawable. Invece, utilizzare il GradientDrawableche viene restituito: GradientDrawable gradientDrawable = (GradientDrawable)imageView.getBackground();.... gradientDrawable.setColors(new int[] { color1, color2 });.
Vikram,

2
Grazie .. mi ha salvato il mondo.
sid_09,

43

Fai così:

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

1
@ user3111850 Hai aggiunto android:backgroundl'xml o addirittura l' setBackgroundattività prima di chiamare getBackground()? Dovrebbe funzionare se lo avessi fatto.
Lee Yi Hong,

41

Al giorno d'oggi una soluzione più semplice sarebbe quella di utilizzare la tua forma come sfondo e quindi modificare a livello di codice il suo colore tramite:

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

Vedi PorterDuff.Mode per le opzioni disponibili.

AGGIORNAMENTO (API 29):

Il metodo sopra è obsoleto dall'API 29 e sostituito dal seguente:

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

Vedi BlendMode per le opzioni disponibili.


4
Uno corretto è: view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_ATOP);poiché potrebbe esserci un bordo sullo sfondo o arrotondatori arrotondati.
Berkay Turancı,

1
Bello uno @ BerkayTurancı la mia forma aveva angoli arrotondati. Potrei omettere la getBackground()chiamata. Il mio imageview.src conteneva una forma e l'ho usato: imageIndicator.setColorFilter(toggleColor, PorterDuff.Mode.SRC_ATOP);dove toggleColorè solo un int che precedentemente memorizzava il risultato da getColor ()
Someone Somewhere

1
Avere PorterDuff.Modeper BlendModeColorFilternon compilerà come richiesto BlendMode. Quindi per API 29 dovrebbe essere view.background.colorFilter = BlendModeColorFilter(Color.parseColor("#343434"), BlendMode.SRC_ATOP).
Onik,

Buona cattura @Onik. Ho aggiornato la risposta di conseguenza. Grazie!
Georgios,

14

Prova questo:

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

per maggiori dettagli controlla questo link questo

spero aiuto.


vota per il link. Ma non è la risposta alla mia domanda.
Cote Mounyo,

13

spero che questo possa aiutare qualcuno con lo stesso problema

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
Inizialmente non riuscivo a far funzionare tutto questo, ho capito che il tuo colore deve essere fornito in questo modo:gd.setStroke(width_px, Color.parseColor("#FF5722"));
pwnsauce

12

Espandendo la risposta di Vikram , se stai colorando viste dinamiche, come elementi di visualizzazione riciclatore, ecc. Quindi probabilmente vorrai chiamare mutate () prima di impostare il colore. In caso contrario, anche le viste che hanno un disegno comune (ad esempio uno sfondo) avranno il loro disegno modificabile / colorato.

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
esigenze e controllo e parametro extra: if (background instanceof LayerDrawable) { background = ((LayerDrawable) background.mutate()).getDrawable(indexIfLayerDrawable); } if (background instanceof ShapeDrawable)[...]per gestire i layout di sfondi che usano <layer-list ... <item ....
Johny,

11

A questa domanda è stata data risposta qualche tempo fa, ma può essere modernizzata riscrivendola come una funzione di estensione kotlin.

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

7

questa è la soluzione che funziona per me ... l'ho scritta anche in un'altra domanda: come cambiare dinamicamente il colore della forma?

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

Niente funziona per me, ma quando imposto il colore della tinta funziona su Shape Drawable

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

richiede Android 5.0 API 21


3

La mia versione della funzione di estensione Kotlin si basa sulle risposte sopra con 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

Il modo semplice per riempire la forma con il raggio è:

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

1

Forse sono troppo tardi, ma se stai usando Kotlin. C'è un modo come questo

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)

Godere....


0

Per chiunque usi C # Xamarin, ecco un metodo basato sullo snippet di 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;
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.