Como mudar a cor da forma dinamicamente?

136

eu tenho

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

Então agora eu quero que essa forma mude de cores com base nas informações que recebo de uma chamada de serviço da web. Talvez seja amarelo, verde ou vermelho, ou o que for, dependendo da cor que recebo da chamada de serviço da Web.

Como posso mudar a cor da forma? Com base nesta informação?

chobo2
fonte
3
Conforme indicado pelo método @Couitchy, View.getBackground()retorna a GradientDrawablee não ShapeDrawablecausa a falha do aplicativo em tempo de execução, devido à conversão inválida ao tentar obter a referência e definir a cor programaticamente. [Android Shape doc] ( developer.android.com/guide/topics/resources/… ) declara: DATATYPE DE RECURSOS COMPLETOS: ponteiro de recurso para aGradientDrawable .
Luis Quijada
Possível duplicado de Set cor forma android programaticamente
Amin Soheyli

Respostas:

300

Você pode modificá-lo simplesmente assim

GradientDrawable bgShape = (GradientDrawable)btn.getBackground();
bgShape.setColor(Color.BLACK);
Ronnie
fonte
9
O que é o btn.getBackground?
Ch232
16
Estou recebendo java.lang.ClassCastException: android.graphics.drawable.GradientDrawable cannot be cast to android.graphics.drawable.ShapeDrawableao tentar esta sugestão.
Prolink007
2
Não funciona. Você receberá um erro de conversão. Precisa de uma correção ou outra resposta aceita
ndgreen
6
Isso funciona muito bem. Os comentários anteriores estão desatualizados desde que a resposta foi editada!
W3hri 06/07/2015
4
Você deve usar GradientDrawable bgShape = (GradientDrawable) btn.getBackground (). getCurrent ();
usar o seguinte código
60

Para mim, ele caiu porque getBackgroundretornou uma GradientDrawablevez de um ShapeDrawable.

Então eu modifiquei assim:

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

Isso funciona para mim, com um 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 do exposto acima: http://i.stack.imgur.com/hKUR7.png

Manuel V.
fonte
Essa é a resposta correta. As duas respostas anteriores não foram trabalhadas para mim. Estou recebendo exceção em ambos.
Sanal Varghese
10

Você pode criar suas próprias formas em Java. Eu fiz isso para um iPhone como o Page Controler e pintei as formas em 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 isto ajude. Greez Fabian

Fabian
fonte
7

Talvez alguém precise alterar a cor no XML sem criar vários drawables como eu precisava. Em seguida, crie um círculo desenhável sem cor e especifique backgroundTint para o 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 no seu layout :

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

Editar:

Há um erro nesse método que impede que ele funcione no Android Lollipop 5.0 (nível de API 21). Mas foram corrigidos em versões mais recentes.

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

fonte
Onde round_button_shape deve definir no arquivo xml de forma?
Jayesh
5

circle.xml (desenhável)

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

disposiçã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"/>

em atividade

   circleColor = (ImageView) view.findViewById(R.id.circleColor);
   int color = Color.parseColor("#00FFFF");
   ((GradientDrawable)circleColor.getBackground()).setColor(color);
A. Shukri
fonte
Não é perfeito, mas me ajudou a obter a solução.
Rakesh Yadav
2

Esta solução funcionou para mim usando o 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)

fonte
2

Se você tem um imageView assim:

   <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 dão a ele uma forma desenhável como src, você pode usar este código para alterar a cor da forma:

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

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

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

Minha atividade java:

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

Imagem do resultado : resultado

Abner_Ni
fonte
1

A maneira mais simples de preencher a forma com o Radius é:

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

Eu tento a resposta de Ronnie e meu aplicativo falhou. Então eu verifico meu xml drawable. Se parece com isso:

<selector >...</selector>

. Eu mudei para isso: (também alterei atributos)

<shape> ... </shape>

Funciona.

Para quem encontra o mesmo problema.

liang
fonte
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));
Ketan Ramani
fonte
0

Você pode usar um adaptador de ligação (Kotlin) para conseguir isso. Crie uma classe de adaptador de ligação denominada ChangeShapeColor como abaixo

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

Crie uma forma desenhável na pasta res / drawable. Eu criei um círculo

<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, consulte-o

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