Change Chip Widget style programmatically not working - Android
Asked Answered
D

6

36

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"/>
Dabster answered 30/11, 2018 at 12:44 Comment(0)
R
64

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);
Rosetta answered 5/10, 2019 at 10:13 Comment(5)
Option one works perfectly. With the second option, chip's selected text colors does not change as per defined style. While cross checking with source code, could find chipDrawable.setShouldDrawText(false); in setChipDrawable method defined in com.google.android.material.chip .Not sure why textview was implemented this way, preventing editing programmatically. Comment in source says Defers to TextView to draw the text and ChipDrawable to render the rest (e.g. chip / check / close icons)Pearle
@Pearle if you also pass your custom style to chip.setTextAppearance method you can have the complete behaviour with the 2nd option of Gabriele MariottiThereunder
Tried Option 2 by setting the same style to text appearance as suggested by @Irving Lop but doesn't seem to work for me. When the Chip is selected the text colour isn't changing as per the defined style.Babita
I have followed Option 1, It works perfectly. I have one query -> Can we set a Parcelized Object data on Chip, so that if the chip is checked then we can extract the required value from it. for e.g. - model with id & name on-chip itself?Boyes
THIS IS SOLUTION FAR BEST ON THE INTERNET. EVEN IN 2023Sunda
P
17

In order to set the chip style in code you can try the following:

val chip = Chip(context)
val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_MaterialComponents_Chip_Choice)
chip.setChipDrawable(drawable)
Peloria answered 30/4, 2019 at 17:0 Comment(0)
B
11

the CustomChipChoice is not a style it is just a reference to a style. therefore change R.style.CustomChipChoice to it : R.attr.CustomChipChoice

val newChip = Chip(context, null, R.attr.CustomChipChoice)

but before it you should add this CustomChipChoicein values.xml file in your project. for this. if your project does not have the values.xml create it in values directory.

then add CustomChipChoice like this.

values.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="CustomChipChoice" format="reference" />
</resources>

now in styles.xml add your style like this.

styles.xml

<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
        .
        .
        <item name="CustomChipChoice">@style/CustomChipChoiceStyle</item>
        .
        .
</style>

now that CustomChipChoice attr references to this style and now you can create your custom style in styles.xml file.

styles.xml

<style name="CustomChipChoiceStyle" parent="@style/Widget.MaterialComponents.Chip.Action">
        .
        <item name="checkedIconVisible">false</item>
        <item name="android:focusable">true</item>
        <item name="android:clickable">true</item>
        <item name="chipBackgroundColor">@color/colorWhite</item>
        <item name="chipIcon">@drawable/ic_filter</item>
        <item name="chipIconVisible">true</item>
        <item name="textStartPadding">0dp</item>
        <item name="textEndPadding">0dp</item>
        .
        .
        <item name="android:textAppearance">@style/ChipTextStyleAppearance</item>
</style>

if you want to change text appearance of chip. here is ChipTextStyleAppearance. you can add it like this.

styles.xml

<style name="ChipTextStyleAppearance">
        <item name="android:fontFamily">@font/main_font</item>
        <item name="android:textSize">13dp</item>
        <item name="android:textColor">#ffffff</item>
</style>

dont forget to add the AppTheme in androidManifest.xml on application or activity tags.

androidManifest.xml

<application
        .
        .
        android:theme="@style/AppTheme">

<activity
            .
            .
            android:theme="@style/AppTheme" />
Bloch answered 18/12, 2019 at 10:53 Comment(0)
C
1

There's another very simple approach to this.

styles.xml

<style name="Widget.MyApp.Chip" parent="Widget.MaterialComponents.Chip.Choice">
    <item name="android:textAppearance">@style/TextAppearance.MyApp.Chip</item>
    <item name="chipIconTint">?attr/colorPrimary</item>
</style>

theme.xml

<style name="Theme.MyApp.MyTheme" parent="Base.Theme.MyApp">
    <item name="chipStyle">@style/Widget.MyApp.Chip</item>
</style>

With this, all chips in activities that have the theme Theme.MyApp.MyActivity applied to it will follow this custom style whether the chip has been added through xml or programmatically.

Cumine answered 3/11, 2021 at 6:3 Comment(0)
B
0

Kotlin

xml

    <com.google.android.material.chip.ChipGroup
                android:id="@+id/chipGroup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">
</com.google.android.material.chip.ChipGroup>

Class

 data class Parametro(
       var idParametro: Long,
       var nombreParametro: String? )

Main

        listParametro.forEach { it->
                    val chip = Chip(context)
                    chip.id= it.idParametro.toInt()
                    chip.text= it.nombreParametro
                    chip.isClickable = true
                    chip.isCheckable = true
                    chip.setOnCheckedChangeListener { buttonView, isChecked ->
                        Log.i("checkedChipIds","${buttonView.id} $isChecked")
                    }
                    mBinding.chipGroup.addView(chip)
                }

it works for me :)

Bedplate answered 31/5, 2021 at 20:50 Comment(0)
H
0

Define Styles in themes.xml

 <!-- Base application theme. -->
<style name="Theme.App" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    ....
    <item name="chipStyle">@style/Widget.App.Chip</item>
</style>

<style name="Widget.App.Chip" parent="Widget.Material3.Chip.Suggestion">
    <item name="chipIconTint">@color/black</item>
    <item name="chipBackgroundColor">@color/chip_bg_tint</item>
    <item name="chipStrokeWidth">0.5dp</item>
    <item name="chipMinHeight">32dp</item>
    <item name="closeIconVisible">false</item>
    <item name="android:textColor">@color/black</item>
    <item name="chipStrokeColor">@color/stroke_tint</item>
    <item name="checkedIconVisible">false</item>
    <item name="android:textAppearance">@style/chipTextAppearance</item>
    <item name="shapeAppearance">@style/ShapeAppearance.App.SmallComponent</item>
</style>

<style name="chipTextAppearance" parent="TextAppearance.Material3.BodyMedium">
    <item name="fontFamily">@font/poppins_regular</item>
    <item name="android:fontFamily">@font/poppins_regular</item>
    <item name="android:textSize">12sp</item>
    <item name="android:textStyle">bold</item>
</style>

<style name="ShapeAppearance.App.SmallComponent" parent="ShapeAppearance.Material3.SmallComponent">
    <item name="cornerFamily">rounded</item>
    <item name="cornerSize">6dp</item>
</style>

Then Use this method to dynamically create Chips

val chip = createChip("Himalayas")

private fun createChip(textValue: String): Chip {
    return Chip(context).apply {
        id = ViewCompat.generateViewId()
        val drawable = ChipDrawable.createFromAttributes(context, null,
            0, R.style.Widget_App_Chip)
        setChipDrawable(drawable)
        setTextAppearance(R.style.chipTextAppearance)
        text = textValue
    }
}

And then add the newly created chip to any viewgroup. Eg:

myLinearLayout.addView(chip) OR

myChipGroup.addView(chip)

Output of Dynamically added chips

Hynda answered 10/5, 2023 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.