Come cambiare dinamicamente il colore della forma?


136

io ho

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
   android:shape="rectangle">
    <solid
       android:color="#FFFF00" />
    <padding android:left="7dp"
        android:top="7dp"
        android:right="7dp"
        android:bottom="7dp" />
</shape>

<TextView
    android:background="@drawable/test"
    android:layout_height="45dp"
    android:layout_width="100dp"
    android:text="Moderate"
/>

Quindi ora voglio che questa forma cambi i colori in base alle informazioni che ricevo da una chiamata al servizio web. Quindi potrebbe essere giallo o verde o rosso o qualsiasi altra cosa a seconda del colore che ricevo dalla chiamata serivce web.

Come posso cambiare il colore della forma? Sulla base di queste informazioni?


3
Come stabilito dal metodo @Couitchy, viene View.getBackground()restituito un GradientDrawablee non un ShapeDrawablearresto anomalo dell'app in fase di runtime, a causa di cast non valido quando si tenta di ottenere il riferimento e impostare il colore a livello di codice. [ Documento Android Shape] ( developer.android.com/guide/topics/resources/… ) afferma: DATATYPE RISORSE COMPILATE: puntatore delle risorse a aGradientDrawable .
Luis Quijada,

Risposte:


300

Puoi modificarlo semplicemente in questo modo

GradientDrawable bgShape = (GradientDrawable)btn.getBackground();
bgShape.setColor(Color.BLACK);

9
Che cos'è btn.getBackground?
chobo2

16
Ricevo java.lang.ClassCastException: android.graphics.drawable.GradientDrawable cannot be cast to android.graphics.drawable.ShapeDrawablequando provo questo suggerimento.
prolink007,

2
Non funziona. Verrà visualizzato un errore di trasmissione. Richiede una correzione o un'altra risposta accettata
ndgreen

6
Questo funziona bene. I commenti precedenti sono obsoleti da quando la risposta è stata modificata!
W3hri,

4
shoul usa GradientDrawable bgShape = (GradientDrawable) btn.getBackground (). getCurrent ();
navata148

60

Per me, si è bloccato perché getBackgroundrestituito a GradientDrawableanziché a ShapeDrawable.

Quindi l'ho modificato in questo modo:

((GradientDrawable)someView.getBackground()).setColor(someColor);

42

Questo funziona per me, con una risorsa XML iniziale:

example.setBackgroundResource(R.drawable.myshape);
GradientDrawable gd = (GradientDrawable) example.getBackground().getCurrent();
gd.setColor(Color.parseColor("#000000"));
gd.setCornerRadii(new float[]{30, 30, 30, 30, 0, 0, 30, 30});
gd.setStroke(2, Color.parseColor("#00FFFF"), 5, 6);

Risultato di quanto sopra: http://i.stack.imgur.com/hKUR7.png


Questa è la risposta corretta Entrambe le risposte sopra menzionate non hanno funzionato per me. Ricevo un'eccezione per entrambi.
Sanal Varghese,

10

Puoi creare le tue forme in Java. L'ho fatto per un iPhone come Page Controler e per dipingere le forme in Java:

/**
 * Builds the active and inactive shapes / drawables for the page control
 */
private void makeShapes() {

    activeDrawable = new ShapeDrawable();
    inactiveDrawable = new ShapeDrawable();
    activeDrawable.setBounds(0, 0, (int) mIndicatorSize,
            (int) mIndicatorSize);
    inactiveDrawable.setBounds(0, 0, (int) mIndicatorSize,
            (int) mIndicatorSize);

    int i[] = new int[2];
    i[0] = android.R.attr.textColorSecondary;
    i[1] = android.R.attr.textColorSecondaryInverse;
    TypedArray a = this.getTheme().obtainStyledAttributes(i);

    Shape s1 = new OvalShape();
    s1.resize(mIndicatorSize, mIndicatorSize);
    Shape s2 = new OvalShape();
    s2.resize(mIndicatorSize, mIndicatorSize);

    ((ShapeDrawable) activeDrawable).getPaint().setColor(
            a.getColor(0, Color.DKGRAY));
    ((ShapeDrawable) inactiveDrawable).getPaint().setColor(
            a.getColor(1, Color.LTGRAY));

    ((ShapeDrawable) activeDrawable).setShape(s1);
    ((ShapeDrawable) inactiveDrawable).setShape(s2);
}

spero che questo ti aiuti. Greez Fabian


8

Forse qualcun altro ha bisogno di cambiare colore nell'XML senza creare più drawable di cui avevo bisogno. Quindi rendere un cerchio tracciabile senza colore e quindi specificare backgroundTint per ImageView.

circle.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
</shape>

E nel tuo layout :

<ImageView
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:background="@drawable/circle"
    android:backgroundTint="@color/red"/>

Modificare:

Esiste un bug relativo a questo metodo che gli impedisce di funzionare su Android Lollipop 5.0 (livello API 21). Ma sono stati risolti nelle versioni più recenti.


5
    LayerDrawable bgDrawable = (LayerDrawable) button.getBackground();
    final GradientDrawable shape = (GradientDrawable)
            bgDrawable.findDrawableByLayerId(R.id.round_button_shape);
    shape.setColor(Color.BLACK);

Dove dovrebbe essere definito round_button_shape nel file xml di forma?
Jayesh,

5

circle.xml (disegnabile)

<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">

<solid
    android:color="#000"/>

<size
    android:width="10dp"
    android:height="10dp"/>
</shape>

disposizione

<ImageView
      android:id="@+id/circleColor"
      android:layout_width="15dp"
       android:layout_height="15dp"
      android:textSize="12dp"
       android:layout_gravity="center"
       android:layout_marginLeft="10dp"
      android:background="@drawable/circle"/>

in attività

   circleColor = (ImageView) view.findViewById(R.id.circleColor);
   int color = Color.parseColor("#00FFFF");
   ((GradientDrawable)circleColor.getBackground()).setColor(color);

Non perfetto, ma mi ha aiutato a ottenere la soluzione.
Rakesh Yadav,

2

Questa soluzione ha funzionato per me utilizzando Android SDK V19:

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

2

Se disponi di un'immagine come questa:

   <ImageView
    android:id="@+id/color_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="10dp"
    android:src="@drawable/circle_color"/>

che gli danno una forma disegnabile come src, puoi usare questo codice per cambiare il colore della forma:

ImageView iv = (ImageView)findViewById(R.id.color_button);
GradientDrawable bgShape = (GradientDrawable)iv.getDrawable();
bgShape.setColor(Color.BLACK);

1

La mia forma xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid  android:color="@android:color/transparent" />
<stroke android:width="0.5dp" android:color="@android:color/holo_green_dark"/>
</shape>

La mia attività xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="cn.easydone.test.MainActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />
    <TextView
        android:id="@+id/test_text"
        android:background="@drawable/bg_stroke_dynamic_color"
        android:padding="20dp"
        android:text="asdasdasdasd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</android.support.design.widget.AppBarLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:clipToPadding="false"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

La mia attività java:

 TextView testText = (TextView) findViewById(R.id.test_text);
 ((GradientDrawable)testText.getBackground()).setStroke(10,Color.BLACK);

Immagine del risultato : risultato


1

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

XML:

<TextView
    android:id="@+id/textView"
    android:background="@drawable/test"
    android:layout_height="45dp"
    android:layout_width="100dp"
    android:text="Moderate"/>

Giava:

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

0

Provo la risposta di Ronnie e la mia app si è bloccata. Quindi controllo il mio XML estraibile. Sembra così:

<selector >...</selector>

. L'ho cambiato in questo: (anche cambiato gli attributi)

<shape> ... </shape>

Funziona.

Per coloro che incontrano lo stesso problema.


0

drawable_rectangle.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="@android:color/transparent" />

    <stroke
        android:width="1dp"
        android:color="#9f9f9f" />

    <corners
        android:bottomLeftRadius="5dp"
        android:bottomRightRadius="5dp"
        android:topLeftRadius="5dp"
        android:topRightRadius="5dp" />

</shape>

TextView

<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/drawable_rectangle"
    android:gravity="center"
    android:padding="10dp"
    android:text="Status"
    android:textColor="@android:color/white"
    android:textSize="20sp" />


public static void changeRectangleColor(View view, int color) {
    ((GradientDrawable) view.getBackground()).setStroke(1, color);
}    

changeRectangleColor(textView, ContextCompat.getColor(context, R.color.colorAccent));

0

È possibile utilizzare un adattatore di rilegatura (Kotlin) per raggiungere questo obiettivo. Creare una classe di adattatore di associazione denominata ChangeShapeColor come di seguito

@BindingAdapter("shapeColor")

// Method to load shape and set its color 

fun loadShape(textView: TextView, color: String) {
// first get the drawable that you created for the shape 
val mDrawable = ContextCompat.getDrawable(textView.context, 
R.drawable.language_image_bg)
val  shape =   mDrawable as (GradientDrawable)
// use parse color method to parse #34444 to the int 
shape.setColor(Color.parseColor(color))
 }

Crea una forma disegnabile nella cartella res / drawable. Ho creato un cerchio

<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<solid android:color="#anyColorCode"/>

<size
    android:width="@dimen/dp_16"
    android:height="@dimen/dp_16"/>
</shape>

Infine, rimandalo alla tua vista

  <TextView>
   .........
  app:shapeColor="@{modelName.colorString}"
 </Textview>
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.