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?

chobo2
la source
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
Copie

Réponses:

300

Vous pouvez le modifier simplement comme ceci

GradientDrawable bgShape = (GradientDrawable)btn.getBackground();
bgShape.setColor(Color.BLACK);
Ronnie
la source
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);
Couitchy
la source
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

Manuel V.
la source
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

Fabien
la source
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.

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

la source
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);
A. Shukri
la source
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)

la source
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);
Hamed Ghadirian
la source
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

Abner_Ni
la source
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);
SANAT
la source
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.

liang
la source
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));
Ketan Ramani
la source
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>
Rohan Sharma
la source