以编程方式更改芯片小部件样式无效 - Android

36

我正在使用芯片列表,我希望这些芯片可以被选择,因此查看https://material.io/develop/android/components/chip/后,我发现我可以使用“Choice 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 实现如下效果:

自定义 ChipChoice 样式

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

背景色芯片状态列表

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

正如您所见,我使芯片可点击和可选中(隐藏我不需要的复选标志)。

但是当我测试它时,颜色未设置。芯片只是默认颜色(灰度)。

在哪里可以应用这个自定义样式?

P.S:

我进行了快速测试,以查看我的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个回答

61

由于第三个参数并非样式而是主题中的属性R.attr.chipStyle,因此您无法使用构造函数val chip = Chip(context, null, R.style.CustomChipChoice)
Chip没有像其他组件一样具有4个参数的构造函数,因为它扩展了不支持4个参数构造函数的AppCompatCheckbox

但是,您可以使用其他选项:
第一种选项:

只需使用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);

第二种选择:

另一个选项是使用 setChipDrawable 方法来覆盖 Chip 内部的 ChipDrawable:

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

7
选项一运作良好。使用选项二时,芯片的所选文本颜色不会按定义的样式更改。在查阅源代码时,在 com.google.android.material.chip 中定义的 setChipDrawable 方法中找到了 chipDrawable.setShouldDrawText(false);。不确定为什么 TextView 被以这种方式实现,可以通过编程方式进行编辑。源代码中的注释说:“将绘制文本和 ChipDrawable 渲染其他部分(例如芯片/检查/关闭图标)委托给 TextView”。 - Sreehari
@Sreehari 如果你也将自定义样式传递给chip.setTextAppearance方法,你就可以获得Gabriele Mariotti的第二个选项的完整行为。 - Irving Dev
尝试了选项2,按照@Irving Lop建议的将相同的样式设置为文本外观,但对我似乎没有起作用。当选择芯片时,文本颜色不会根据定义的样式更改。 - Siddhivinayak
我已经按照选项1进行了操作,它完美地运行。我有一个问题->我们是否可以在芯片上设置一个Parcelized对象数据,以便如果选中芯片,则可以从中提取所需的值。例如-模型与ID和名称本身就在芯片上? - Dharamveer Mithilesh Gupta
1
这是互联网上最好的解决方案,即使在2023年也是如此。 - undefined

15

为了在代码中设置芯片样式,您可以尝试以下操作:

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

11

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属性引用了这个样式,现在您可以在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>

不要忘记在 applicationactivity 标签中的 androidManifest.xml 中添加 AppTheme

androidManifest.xml

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

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

1

有另一种非常简单的方法。

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还是以编程方式添加的。


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>

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

这对我有效 :)


0

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

然后将新创建的芯片添加到任何ViewGroup中。例如:

myLinearLayout.addView(chip) OR

myChipGroup.addView(chip)

动态添加芯片的输出


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接