Change Chip Widget style programmatically not working - Android

Shudy picture Shudy · Nov 30, 2018 · Viewed 10.7k times · Source

I'm doing a list with Chips. I want this chips can be selected, so, taking a look to https://material.io/develop/android/components/chip/ I see I can have a "Choice Chip".

As I need to create and add dynamically I have to configure with specific colors, color ripplem, ...

So what I have to configure it is:

val chip = Chip(context, null, R.style.CustomChipChoice)
            chip.isClickable = true
            chip.isCheckable = true
            chip.isCheckedIconVisible=false
            chip.height = ScreenUtils.dpToPx(40)
            chip.chipCornerRadius = (ScreenUtils.dpToPx(20)).toFloat()
            chip.chipStrokeWidth = (ScreenUtils.dpToPx(2)).toFloat()
            chip.setTextAppearanceResource(R.style.ChipTextStyle)
            return chip

What I try with R.style.CustomChipChoice is:

CustomChipChoice style

<style name="CustomChipChoice" parent="@style/Widget.MaterialComponents.Chip.Choice">
        <item name="chipBackgroundColor">@color/background_color_chip_state_list</item>
        <item name="chipStrokeColor">@color/background_color_chip_state_list</item>
        <item name="rippleColor">@color/topic_social_pressed</item>
</style>

background_color_chip_state_list

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/topic_social_selected" android:state_checked="true" />
    <item android:color="@color/topic_social_pressed" android:state_pressed="true" />
    <item android:color="@color/topic_unselected_background" />
</selector>

stroke_color_chip_state_list

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/topic_social_pressed" android:state_checked="true"/>
    <item android:color="@color/grey_material2" android:state_checked="false"/>
</selector>

As you can see, I make the chip, clickable and checkable (hiding the check icon I don't need).

But when I test it, the colors are not set. The chips just look as default colors (grey's scale)

Where can I apply or how, this custom style?

P.S:

I have done a fast test, to see if my CustomStyle was malformed/etc..

I added a view via xml and worked perfectly...

<android.support.design.chip.Chip
                android:id="@+id/test"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/CustomChipChoice"
                android:checkable="true"
                android:clickable="true"
                app:checkedIconVisible="false"
                android:text="Chip Test"/>

Answer

Gabriele Mariotti picture Gabriele Mariotti · Oct 5, 2019

You can't use the constructor val chip = Chip(context, null, R.style.CustomChipChoice) because the 3rd parameter isn't the style but the attribute in the theme as R.attr.chipStyle.
The Chip hasn't a constructor with 4 parameters as other components because it extends AppCompatCheckbox which does not support a 4 parameter constructor.

However you can use something different.
1st option:

Just use a xml layout (single_chip_layout.xml) to define the single Chip with your favorite style:

<com.google.android.material.chip.Chip
    xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/CustomChipChoice"
    ...
/>

with

<style name="CustomChipChoice" parent="@style/Widget.MaterialComponents.Chip.Choice">
...
</style>

Then instead of val chip = Chip(context, null, R.style.CustomChipChoice) use:

val chip = layoutInflater.inflate(R.layout.single_chip_layout, chipGroup, false) as Chip

In java:

Chip chip =
          (Chip) getLayoutInflater().inflate(R.layout.single_chip_layout, chipGroup, false);

2nd option:

Another option is to use the setChipDrawable method to override the ChipDrawable inside the Chip:

  Chip chip = new Chip(this);
  ChipDrawable chipDrawable = ChipDrawable.createFromAttributes(this,
      null,
      0,
      R.style.Widget_MaterialComponents_Chip_Choice);
  chip.setChipDrawable(chipDrawable);