如何为动态添加的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
相关产品推荐
相关产品推荐

