Изменение стиля Chip Widget программно не работает - Android

Я делаю список с чипами. Я хочу, чтобы эти чипы можно было выбирать, поэтому, посмотрев на https://material.io/develop/android/components/chip/ я вижу, что у меня может быть "Выборочный чип".

Поскольку мне нужно создавать и добавлять динамически, я должен настроить с определенными цветами, цветовой рябью,...

Так что я должен настроить это:

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

Что я пытаюсь с R.style.CustomChipChoice является:

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>

Как видите, я делаю чип, кликабельный и проверяемый (скрывая значок проверки, который мне не нужен).

Но когда я проверяю это, цвета не установлены. Чипы просто выглядят как цвета по умолчанию (шкала Грея)

Где я могу применить или как, этот стиль?

PS:

Я сделал быстрый тест, чтобы увидеть, был ли мой CustomStyle деформирован / и т.д..

Я добавил вид через XML и работал отлично...

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

6 ответов

Вы не можете использовать конструкторval chip = Chip(context, null, R.style.CustomChipChoice)потому что третий параметр - это не стиль, а атрибут в теме какR.attr.chipStyle.
ВChip не имеет конструктора с 4 параметрами, как другие компоненты, потому что он расширяет AppCompatCheckbox который не поддерживает конструктор с 4 параметрами.

Однако вы можете использовать что-то другое.
1-й вариант:

Просто используйте макет xml (single_chip_layout.xml) для определения единого Chipс вашим любимым стилем:

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

с

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

Тогда вместо val chip = Chip(context, null, R.style.CustomChipChoice) использование:

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

В java:

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

2 вариант:

Другой вариант - использовать setChipDrawable метод для переопределения ChipDrawable внутри Chip:

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

Чтобы установить стиль чипа в коде, вы можете попробовать следующее:

val chip = Chip(context)
val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_MaterialComponents_Chip_Choice)
chip.setChipDrawable(drawable)

То CustomChipChoiceэто не стиль, это просто ссылка на стиль. поэтому изменитеR.style.CustomChipChoice к нему: R.attr.CustomChipChoice

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

но перед этим вы должны добавить это CustomChipChoiceв values.xmlфайл в вашем проекте. за это. если в вашем проекте нетvalues.xml создать это в values каталог.

затем добавьте CustomChipChoice как это.

values.xml

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

Сейчас в styles.xml добавьте свой стиль вот так.

styles.xml

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

теперь это CustomChipChoice attr ссылается на этот стиль, и теперь вы можете создать свой собственный стиль в styles.xml файл.

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>

если вы хотите изменить внешний вид текста чипа. вотChipTextStyleAppearance. вы можете добавить это вот так.

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>

не забудьте добавить AppTheme в androidManifest.xml на application или activity теги.

androidManifest.xml

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

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

Есть еще один очень простой подход.

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>

При этом все фишки в мероприятиях, имеющих тему Theme.MyApp.MyActivity примененный к нему будет следовать этому пользовательскому стилю, независимо от того, был ли чип добавлен через xml или программно.

Определите стили в файле 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>

Затем используйте этот метод для динамического создания чипов.

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

А затем добавьте вновь созданный чип в любую группу просмотра. Например:

      myLinearLayout.addView(chip) OR

myChipGroup.addView(chip)

Вывод динамически добавляемых чипов

Котлин

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>

Класс

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

Основной

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

меня устраивает :)