Comment changer la couleur de la forme de manière dynamique?


136

j'ai

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

Alors maintenant, je veux que cette forme change de couleur en fonction des informations que je reçois d'un appel de service Web. Cela peut donc être jaune, vert ou rouge ou autre, selon la couleur que je reçois de l'appel de service Web.

Comment puis-je changer la couleur de la forme? Sur la base de ces informations?


3
Comme indiqué par la méthode @Couitchy, View.getBackground()retourne un GradientDrawableet non un, ShapeDrawablece qui provoque le blocage de l'application au moment de l'exécution, en raison d'une distribution non valide lors de la tentative d'obtention de la référence et de la définition de la couleur par programme. [Android Shape doc] ( developer.android.com/guide/topics/resources/… ) indique: DATATYPE DE RESSOURCES COMPILÉES: pointeur de ressource vers un fichierGradientDrawable .
Luis Quijada

Réponses:


300

Vous pouvez le modifier simplement comme ceci

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

9
Qu'est-ce que btn.getBackground?
chobo2

16
Je reçois java.lang.ClassCastException: android.graphics.drawable.GradientDrawable cannot be cast to android.graphics.drawable.ShapeDrawableen essayant cette suggestion.
prolink007

2
Ne marche pas. Vous obtiendrez une erreur de diffusion. Besoin d'un correctif ou d'une autre réponse acceptée
ndgreen

6
Cela fonctionne très bien. Les commentaires précédents sont obsolètes puisque la réponse a été modifiée!
W3hri

4
doit utiliser GradientDrawable bgShape = (GradientDrawable) btn.getBackground (). getCurrent ();
naveed148 le

60

Pour moi, il s'est écrasé car getBackgroundrenvoyé un GradientDrawableau lieu d'un ShapeDrawable.

Alors je l'ai modifié comme ceci:

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

42

Cela fonctionne pour moi, avec une ressource xml initiale:

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

Résultat de ce qui précède: http://i.stack.imgur.com/hKUR7.png


C'est la bonne réponse. Les deux réponses ci-dessus n'ont pas fonctionné pour moi. Je reçois une exception sur les deux.
Sanal Varghese

10

Vous pouvez créer vos propres formes en Java. J'ai fait cela pour un iPhone comme Page Controler et j'ai peint les formes en 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);
}

J'espère que cela t'aides. Greez Fabian


8

Peut-être que quelqu'un d'autre doit changer de couleur dans le XML sans créer plusieurs dessinables comme j'en avais besoin. Ensuite, créez un cercle dessinable sans couleur, puis spécifiez backgroundTint pour ImageView.

circle.xml

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

Et dans votre mise en page :

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

Éditer:

Il y a un bug concernant cette méthode qui l'empêche de fonctionner sur Android Lollipop 5.0 (API niveau 21). Mais ont été corrigés dans les versions plus récentes.


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

Où round_button_shape doit-il définir dans le fichier xml de forme?
Jayesh

5

circle.xml (dessinable)

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

disposition

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

en activité

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

Ce n'est pas parfait, mais cela m'a aidé à trouver la solution.
Rakesh Yadav

2

Cette solution a fonctionné pour moi en utilisant le sdk android 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

Si vous avez une imageView comme celle-ci:

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

qui lui donnent une forme dessinable comme src, vous pouvez utiliser ce code pour changer la couleur de la forme:

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

1

Ma forme 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>

Mon activité 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" />

Mon activité java:

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

Image de résultat : résultat


1

Le moyen le plus simple de remplir la forme avec le rayon est:

XML:

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

Java:

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

0

J'essaye la réponse de Ronnie et mon application s'est plantée. Ensuite, je vérifie mon xml dessinable. Cela ressemble à ceci:

<selector >...</selector>

. Je l'ai changé en ceci: (également changé les attributs)

<shape> ... </shape>

Ça marche.

Pour ceux qui rencontrent le même problème.


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>

Affichage

<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

Vous pouvez utiliser un adaptateur de liaison (Kotlin) pour y parvenir. Créez une classe d'adaptateur de liaison nommée ChangeShapeColor comme ci-dessous

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

Créez une forme dessinable dans le dossier res / drawable. J'ai créé un cercle

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

Enfin renvoyez-le à votre vue

  <TextView>
   .........
  app:shapeColor="@{modelName.colorString}"
 </Textview>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.