代码创建AppCompatRadioButton时buttonTint状态颜色异常问题
问题场景
需要通过Kotlin代码实现与以下XML布局样式完全一致的AppCompatRadioButton:
<androidx.appcompat.widget.AppCompatRadioButton android:id="@+id/radio_btn_ok" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_weight="1" android:background="@drawable/bg_ok_radio_button" android:buttonTint="@drawable/ok_radio_button_text_color" android:paddingRight="10dp" android:text="@string/ok" android:textColor="@drawable/ok_radio_button_text_color" />
我编写的Kotlin代码如下:
val rb = AppCompatRadioButton(this) rb.id = R.id.ok_id rb.background = getDrawable(R.drawable.bg_ok_radio_button) rb.supportButtonTintList = ColorStateList.valueOf(getColor(R.color.ok_radio_button_text_color)) rb.setTextColor(ColorStateList.valueOf(getColor(R.color.ok_radio_button_text_color)))
用到的资源文件:
Drawable目录下bg_radio_button.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/bg_ok_radio_button_selected" android:state_checked="true" /> <item android:drawable="@color/transparent" android:state_checked="false" /> </selector>
Color目录下ok_radio_button_text_color.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:color="@color/white"/> <item android:color="@color/stateGreen"/> </selector>
问题现象:XML实现的RadioButton选中时,按钮tint和文字颜色会切换为白色;但代码创建的RadioButton选中时,tint和文字颜色始终为绿色,不符合预期,必须通过代码方式解决。
问题原因与解决方案
问题根源
代码中使用ColorStateList.valueOf(getColor(R.color.ok_radio_button_text_color))是错误的:
getColor()只能获取到颜色选择器里的默认颜色(即未选中时的绿色)ColorStateList.valueOf()会把这个单一颜色包装成固定的ColorStateList,完全丢失了选择器里的状态切换逻辑
修正后的代码
直接加载带状态的颜色选择器资源,而不是提取单一颜色:
val rb = AppCompatRadioButton(this) rb.id = R.id.ok_id // 加载背景Drawable rb.background = ContextCompat.getDrawable(this, R.drawable.bg_ok_radio_button) // 加载带状态的按钮tint颜色列表 rb.supportButtonTintList = ContextCompat.getColorStateList(this, R.color.ok_radio_button_text_color) // 加载带状态的文字颜色列表 rb.setTextColor(ContextCompat.getColorStateList(this, R.color.ok_radio_button_text_color)) // 补充XML中缺失的布局属性 val layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.WRAP_CONTENT, dpToPx(this, 30) ).apply { weight = 1f } rb.layoutParams = layoutParams rb.setPadding(0, 0, dpToPx(this, 10), 0) rb.setText(R.string.ok)
补充:DP转PX工具函数
用于将XML中的dp值转换为代码中的像素值,放在任意顶层Kotlin文件即可:
fun dpToPx(context: Context, dp: Int): Int { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), context.resources.displayMetrics ).toInt() }
内容的提问来源于stack exchange,提问作者Malo
相关产品推荐
相关产品推荐

