Bagaimana cara mengubah warna bentuk secara dinamis?

136

saya sudah

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

Jadi sekarang saya ingin bentuk ini berubah warna berdasarkan informasi yang saya dapatkan dari panggilan layanan web. Jadi bisa jadi mungkin kuning atau hijau atau merah atau apapun tergantung pada warna yang saya terima dari panggilan layanan web.

Bagaimana cara mengubah warna bentuk? Berdasarkan informasi ini?

chobo2.dll
sumber
3
Seperti yang ditunjuk oleh metode @Couitchy, View.getBackground()mengembalikan GradientDrawabledan bukan ShapeDrawablepenyebab aplikasi mogok pada waktu proses, karena transmisi yang tidak valid saat mencoba mendapatkan referensi dan menyetel warna secara terprogram. [Dok Android Shape] ( developer.android.com/guide/topics/resources/… ) menyatakan: JENIS DATA SUMBER DAYA SELESAI: Penunjuk sumber daya keGradientDrawable .
Luis Quijada
Kemungkinan duplikat Set warna bentuk android secara terprogram
Amin Soheyli

Jawaban:

300

Anda dapat memodifikasinya seperti ini

GradientDrawable bgShape = (GradientDrawable)btn.getBackground();
bgShape.setColor(Color.BLACK);
Ronnie
sumber
9
Apa itu btn.getBackground?
chobo2
16
Saya mendapatkan java.lang.ClassCastException: android.graphics.drawable.GradientDrawable cannot be cast to android.graphics.drawable.ShapeDrawableketika mencoba saran ini.
prolink007
2
Tidak bekerja. Anda akan mendapatkan kesalahan cast. Membutuhkan perbaikan atau jawaban lain diterima
ndgreen
6
Ini bekerja dengan baik. Komentar sebelumnya sudah ketinggalan zaman sejak jawabannya diedit!
W3hri
4
harus menggunakan GradientDrawable bgShape = (GradientDrawable) btn.getBackground (). getCurrent ();
naveed148
61

Bagi saya, itu macet karena getBackgroundmengembalikan a, GradientDrawablebukan a ShapeDrawable.

Jadi saya memodifikasinya seperti ini:

((GradientDrawable)someView.getBackground()).setColor(someColor);
Couitchy
sumber
43

Ini berfungsi untuk saya, dengan sumber daya xml awal:

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

Hasil di atas: http://i.stack.imgur.com/hKUR7.png

Manuel V.
sumber
Ini jawaban yang benar. Kedua jawaban di atas tidak berhasil untuk saya. Saya mendapatkan pengecualian untuk keduanya.
Sanal Varghese
10

Anda dapat membuat bentuk Anda sendiri di Java. Saya melakukan ini untuk iPhone seperti Page Controler dan melukis bentuk di 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);
}

semoga ini membantu. Greez Fabian

Fabian
sumber
8

Mungkin orang lain perlu mengubah warna dalam XML tanpa membuat beberapa sumber daya dapat digambar seperti yang saya butuhkan. Kemudian buat lingkaran yang dapat digambar tanpa warna lalu tentukan backgroundTint untuk ImageView.

circle.xml

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

Dan dalam tata letak Anda :

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

Edit:

Ada bug terkait metode ini yang mencegahnya berfungsi di Android Lollipop 5.0 (API level 21). Tetapi telah diperbaiki di versi yang lebih baru.

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

sumber
Di mana seharusnya round_button_shape didefinisikan dalam bentuk file xml?
Jayesh
5

circle.xml (dapat digambar)

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

tata letak

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

dalam aktivitas

   circleColor = (ImageView) view.findViewById(R.id.circleColor);
   int color = Color.parseColor("#00FFFF");
   ((GradientDrawable)circleColor.getBackground()).setColor(color);
A. Shukri
sumber
Bukan yang sempurna, tapi membantu saya mendapatkan solusinya.
Rakesh Yadav
2

Solusi ini berfungsi untuk saya menggunakan 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)

sumber
2

Jika Anda memiliki imageView seperti ini:

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

yang memberinya bentuk yang dapat digambar sebagai src, Anda dapat menggunakan kode ini untuk mengubah warna bentuk:

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

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

Xml aktivitas saya:

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

Java aktivitas saya:

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

Gambar hasil : hasil

Abner_Ni
sumber
1

Cara termudah untuk mengisi bentuk dengan Radius adalah:

XML:

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

Jawa:

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

Saya mencoba jawaban Ronnie, dan aplikasi saya macet. Lalu saya memeriksa xml drawable saya. Ini terlihat seperti ini:

<selector >...</selector>

. Saya mengubahnya menjadi ini: (juga mengubah atribut)

<shape> ... </shape>

Berhasil.

Bagi mereka yang mengalami masalah yang sama.

liang
sumber
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
sumber
0

Anda dapat menggunakan adaptor binding (Kotlin) untuk melakukannya. Buat kelas adaptor pengikat bernama ChangeShapeColor seperti di bawah ini

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

Buat bentuk drawable dalam folder res / drawable. Saya telah membuat lingkaran

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

Terakhir, rujuk ke pandangan Anda

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