You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为动态添加的Material Chip程序化设置自定义Drawable背景

动态Material Chip的选中/未选中背景设置方案

核心思路

通过**状态选择器(StateListDrawable)**绑定Chip的选中/未选中状态,无论是XML预定义还是代码动态创建,都能实现状态切换时的背景自动变化。


步骤1:准备自定义背景Drawable

方式1:XML预定义状态选择器

在res/drawable下创建chip_background_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 选中状态背景 -->
    <item android:drawable="@drawable/chip_selected_bg" android:state_checked="true"/>
    <!-- 未选中状态背景(默认) -->
    <item android:drawable="@drawable/chip_unselected_bg"/>
</selector>

再分别创建选中/未选中的shape文件:
chip_selected_bg.xml(选中状态):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#2196F3"/>
    <corners android:radius="16dp"/>
    <padding android:bottom="8dp" android:left="16dp" android:right="16dp" android:top="8dp"/>
</shape>

chip_unselected_bg.xml(未选中状态):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#F5F5F5"/>
    <stroke android:color="#E0E0E0" android:width="1dp"/>
    <corners android:radius="16dp"/>
    <padding android:bottom="8dp" android:left="16dp" android:right="16dp" android:top="8dp"/>
</shape>

方式2:代码动态创建StateListDrawable

如果需要完全程序化生成(比如颜色从API获取),直接在代码中构建:

// 工具方法:dp转px
fun Int.dpToPx(resources: Resources): Int = (this * resources.displayMetrics.density).toInt()

// 创建选中状态背景
val selectedBg = GradientDrawable().apply {
    shape = GradientDrawable.RECTANGLE
    setColor(Color.parseColor("#2196F3"))
    cornerRadius = 16.dpToPx(resources).toFloat()
    setPadding(16.dpToPx(resources), 8.dpToPx(resources), 16.dpToPx(resources), 8.dpToPx(resources))
}

// 创建未选中状态背景
val unselectedBg = GradientDrawable().apply {
    shape = GradientDrawable.RECTANGLE
    setColor(Color.parseColor("#F5F5F5"))
    setStroke(1.dpToPx(resources), Color.parseColor("#E0E0E0"))
    cornerRadius = 16.dpToPx(resources).toFloat()
    setPadding(16.dpToPx(resources), 8.dpToPx(resources), 16.dpToPx(resources), 8.dpToPx(resources))
}

// 构建状态选择器
val stateListDrawable = StateListDrawable().apply {
    addState(intArrayOf(android.R.attr.state_checked), selectedBg) // 选中状态
    addState(intArrayOf(), unselectedBg) // 默认未选中状态
}

步骤2:动态创建Chip并绑定背景

从API拿到数据后,循环创建Chip并添加到ChipGroup:

val chipGroup = findViewById<ChipGroup>(R.id.chip_group)
val apiChipLabels = listOf("热门", "新品", "折扣", "包邮") // 模拟API返回的标签列表

apiChipLabels.forEach { label ->
    val chip = Chip(this).apply {
        text = label
        isCheckable = true // 必须开启可选中,否则状态切换不生效
        isClickable = true
        
        // 绑定背景:XML方式
        setChipDrawable(ContextCompat.getDrawable(this@MainActivity, R.drawable.chip_background_selector))
        
        // 或者用代码创建的StateListDrawable:
        // setChipDrawable(stateListDrawable)
        
        // 可选:监听选中状态变化
        setOnCheckedChangeListener { _, isChecked ->
            // 处理选中/取消选中的业务逻辑
            Log.d("Chip", "$label 状态:${if (isChecked) "选中" else "未选中"}")
        }
    }
    // 设置Chip间距
    val layoutParams = ChipGroup.LayoutParams(
        ChipGroup.LayoutParams.WRAP_CONTENT,
        ChipGroup.LayoutParams.WRAP_CONTENT
    )
    layoutParams.setMargins(8.dpToPx(resources), 8.dpToPx(resources), 8.dpToPx(resources), 8.dpToPx(resources))
    chip.layoutParams = layoutParams
    chipGroup.addView(chip)
}

关键注意事项

  • 必须开启isCheckable = true:只有开启此属性,Chip才会触发state_checked状态,背景选择器才会生效。
  • 适配Chip默认样式:自定义背景时要注意内边距、圆角,避免和Chip默认样式冲突导致显示异常。
  • 文字颜色状态适配:如果需要文字颜色随状态变化,可以创建textColor的状态选择器,或用代码设置setTextColor(ColorStateList)。

内容的提问来源于stack exchange,提问作者krupa parekh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:35:55