Neria Nachum
Neria Nachum

Reputation: 1529

Programmatically change solid color in an existing shape

I have a circular view with a customized border, implemented using CircularImageView library and inflated in a RecyclerView. So far I've put an image in it, but now I want to replace it with a single-colored round and a text upon it.

I created the following shape (shape_colored_circle.xml):

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

    <size
        android:height="70dp"
        android:width="70dp"/>
    <solid
        android:color="#00f"/>
</shape>

And added a TextView together with the CircularImageView in a FrameLayout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <com.mikhaellopez.circularimageview.CircularImageView
            android:id="@+id/card_thumbnail"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:src="@drawable/icon"
            app:civ_border="true"
            app:civ_border_color="@color/border_color"
            app:civ_border_width="2dp"
            app:civ_shadow="true"
            app:civ_shadow_color="@color/grey"
            app:civ_shadow_radius="10"
            android:contentDescription="@string/card_thumbnail"/>

        <TextView
            android:id="@+id/card_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/app_name"
            android:textSize="18sp"
            android:textStyle="bold"/>

    </FrameLayout>

</LinearLayout>

I'm aware that the layout seems a bit odd ("why is the top LinearLayout necessary?"), but without it the view simply does not appear in the RecyclerView whereas this layout (which is taken from the library's example) serves our needs.

In onBindViewHolder I set the shape as the CircularImageView resource:

holder.thumbnail.setImageDrawable(activity.getResources().getDrawable(R.drawable.shape_colored_circle));

And finally I see what I was expecting. The problem is that my drawable have a specific color set in advance. Therefore, I tried to create a shape programmatically:

GradientDrawable gd = new GradientDrawable();
gd.setShape(GradientDrawable.RECTANGLE);
gd.setColor(colors[position]);             //Getting the color from a predefined array of colors
holder.thumbnail.setImageDrawable(gd);

But the view just turns into a black rectangle. I tried a few more solutions for creating a shape programmatically (all of them are pretty similar) to no avail - I either see a black rectangle or nothing at all.

Am I doing something wrong? Is there another way to create a shape, or some way to change the existing one at runtime? Or maybe a totally different way to achieve the required behavior?

Thanks!

Upvotes: 1

Views: 1044

Answers (2)

Vijay Pal Vishwakarma
Vijay Pal Vishwakarma

Reputation: 731

   <com.mikhaellopez.circularimageview.CircularImageView
    android:id="@+id/card_thumbnail"
    android:layout_width="70dp"
    android:layout_height="70dp"
    android:background="@drawable/shape_colored_circle" //Note
    android:contentDescription="@string/card_thumbnail"
    android:src="@drawable/icon"
    app:civ_border="true"
    app:civ_border_color="@color/border_color"
    app:civ_border_width="2dp"
    app:civ_shadow="true"
    app:civ_shadow_color="@color/grey"
    app:civ_shadow_radius="10"/>`

GradientDrawable gd = (GradientDrawable) holder.thumbnail.getBackground()
if (gd != null) {
  gd.mutate();
  gd.setColor(colors[position]);
}

Upvotes: 3

Neria Nachum
Neria Nachum

Reputation: 1529

Thanks to Vijay Pal Vishwakarma I managed to solve the case.

First, I set the predefined shape as the source of the CircularImageView:

<com.mikhaellopez.circularimageview.CircularImageView
            android:id="@+id/card_thumbnail"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:src="@drawable/shape_colored_circle"      //Note this line
            app:civ_border="true"
            app:civ_border_color="@color/border_color"
            app:civ_border_width="2dp"
            app:civ_shadow="true"
            app:civ_shadow_color="@color/grey"
            app:civ_shadow_radius="10"
            android:contentDescription="@string/card_followee_large_thumbnail"/>

Then, in onBindViewHolder I get the existing drawable and change its color:

GradientDrawable gd = (GradientDrawable) holder.thumbnail.getDrawable();
if (gd != null) {
    gd.setColor(colors[position]);
}

Upvotes: 1

Related Questions