¿Cómo cambiar el color de la forma dinámicamente?

136

yo tengo

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

Así que ahora quiero que esta forma cambie de color según la información que recibo de una llamada de servicio web. Por lo tanto, podría ser amarillo o verde o rojo o lo que sea, dependiendo del color que reciba de la llamada de servicio web.

¿Cómo puedo cambiar el color de la forma? ¿Basado en esta información?

chobo2
fuente
3
Según lo designado por el método @Couitchy, View.getBackground()devuelve ay GradientDrawableno ShapeDrawablecausa que la aplicación se bloquee en el tiempo de ejecución, debido a una conversión no válida al intentar obtener la referencia y establecer el color mediante programación. [Android Shape doc] ( developer.android.com/guide/topics/resources/… ) afirma: DATATYPE DE RECURSOS COMPILADOS: puntero de recursos a aGradientDrawable .
Luis Quijada

Respuestas:

300

Podrías modificarlo simplemente así

GradientDrawable bgShape = (GradientDrawable)btn.getBackground();
bgShape.setColor(Color.BLACK);
Ronnie
fuente
9
¿Qué es btn.getBackground?
chobo2
16
Estoy obteniendo java.lang.ClassCastException: android.graphics.drawable.GradientDrawable cannot be cast to android.graphics.drawable.ShapeDrawableal intentar esta sugerencia.
prolink007
2
No funciona. Obtendrás un error de lanzamiento. Necesita una solución u otra respuesta aceptada
ndgreen
66
Esto funciona bien. ¡Los comentarios anteriores son obsoletos desde que se editó la respuesta!
W3hri
44
debe usar GradientDrawable bgShape = (GradientDrawable) btn.getBackground (). getCurrent ();
naveed148
60

Para mí, se estrelló porque getBackgrounddevolvió un en GradientDrawablelugar de un ShapeDrawable.

Así que lo modifiqué así:

((GradientDrawable)someView.getBackground()).setColor(someColor);
Couitchy
fuente
42

Esto funciona para mí, con un recurso xml inicial:

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

Resultado de lo anterior: http://i.stack.imgur.com/hKUR7.png

Manuel V.
fuente
Esta es la respuesta correcta. Las dos respuestas anteriores no me funcionaron. Estoy obteniendo una excepción en ambos.
Sanal Varghese
10

Puedes construir tus propias formas en Java. Hice esto para un iPhone como Page Controler y pinté las formas 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);
}

espero que esto ayude. Greez Fabian

Fabian
fuente
7

Tal vez alguien más necesite cambiar el color en el XML sin crear múltiples dibujables como yo necesitaba. Luego haga un círculo dibujable sin color y luego especifique backgroundTint para ImageView.

circle.xml

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

Y en tu diseño :

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

Editar:

Hay un error con respecto a este método que impide que funcione en Android Lollipop 5.0 (API nivel 21). Pero se han solucionado en versiones más nuevas.

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

fuente
¿Dónde debería definir round_button_shape en el archivo xml de forma?
Jayesh
5

circle.xml (dibujable)

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

diseño

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

   circleColor = (ImageView) view.findViewById(R.id.circleColor);
   int color = Color.parseColor("#00FFFF");
   ((GradientDrawable)circleColor.getBackground()).setColor(color);
A. Shukri
fuente
No es perfecto, pero me ayudó a encontrar la solución.
Rakesh Yadav
2

Esta solución funcionó para mí usando el 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)

fuente
2

Si tienes una imagen como esta:

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

que le dan una forma dibujable como src, puedes usar este código para cambiar el color de la forma:

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

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

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

Mi actividad java:

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

Cuadro del resultado : resultado

Abner_Ni
fuente
1

La forma más sencilla de llenar la forma con el Radio es:

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

Intento la respuesta de Ronnie, y mi aplicación falló. Luego reviso mi xml dibujable. Se parece a esto:

<selector >...</selector>

. Lo cambié a esto: (también cambié los atributos)

<shape> ... </shape>

Funciona.

Para aquellos que encuentran el mismo problema.

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

Vista de texto

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

Puede usar un adaptador de enlace (Kotlin) para lograr esto. Cree una clase de adaptador de enlace denominada ChangeShapeColor como se muestra a continuación

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

Cree una forma dibujable en la carpeta res / drawable. He creado un circulo

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

Finalmente refiéralo a su punto de vista

  <TextView>
   .........
  app:shapeColor="@{modelName.colorString}"
 </Textview>
Rohan Sharma
fuente