一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

XML Shape/Selector 转 Kotlin 动态创建

时间:2026-06-03 10:10:01 编辑:袖梨 来源:一聚教程网

传统安卓开发依赖XML定义Shape和Selector,但存在颜色硬编码、重复代码与文件冗余问题。以下展示如何用Kotlin动态创建可配置的圆角按钮背景,替代XML写法。

XML Shape/Selector → Kotlin 动态创建

老写法(XML drawable)

res/drawable/bg_rounded_button.xml

XML Shape/Selector → Kotlin 动态创建

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#4CAF50"/>
    <corners android:radius="8dp"/>
    <stroke android:width="1dp" android:color="#388E3C"/>
shape>

res/drawable/selector_button.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#388E3C"/>
            <corners android:radius="8dp"/>
        shape>
    item>
    <item>
        <shape>
            <solid android:color="#4CAF50"/>
            <corners android:radius="8dp"/>
        shape>
    item>
selector>

Java 中使用:

view.setBackgroundResource(R.drawable.selector_button);

问题在哪里

XML drawable 有三个局限:颜色写死不能动态改、不同状态下要写多份 shape 重复代码、需要在 res/drawable 里维护一堆小文件。

新写法(Kotlin 动态创建)

fun roundedButtonBg(
    context: Context,
    normalColor: Int,
    pressedColor: Int,
    cornerRadiusDp: Int,
    strokeColor: Int,
    strokeWidthDp: Int = 1
): StateListDrawable {
    val density = context.resources.displayMetrics.density
    val radius = cornerRadiusDp * density
    val strokeWidth = strokeWidthDp * density    val normal = GradientDrawable().apply {
        shape = GradientDrawable.RECTANGLE
        setColor(normalColor)
        cornerRadius = radius
        setStroke(strokeWidth.toInt(), strokeColor)
    }    val pressed = GradientDrawable().apply {
        shape = GradientDrawable.RECTANGLE
        setColor(pressedColor)
        cornerRadius = radius
        setStroke(strokeWidth.toInt(), strokeColor)
    }    return StateListDrawable().apply {
        addState(intArrayOf(android.R.attr.state_pressed), pressed)
        addState(intArrayOf(), normal)
    }
}

使用:

view.background = roundedButtonBg(
    context = context,
    normalColor = Color.parseColor("#4CAF50"),
    pressedColor = Color.parseColor("#388E3C"),
    cornerRadiusDp = 8,
    strokeColor = Color.parseColor("#388E3C")
)

一句话注意

GradientDrawable.cornerRadiussetStroke 的参数单位是像素,不是 dp。传 dp 值必须乘以 density,否则不同分辨率手机上圆角大小不一致。StateListDrawable.addState 的状态数组顺序很重要,越具体的状态(如 state_pressed)要放在前面,默认状态(空数组)放最后。


通过Kotlin动态创建StateListDrawable与GradientDrawable,彻底摆脱XML硬编码与重复文件,实现颜色、圆角、描边等参数的灵活配置。本系列将持续探索Java旧项目迁移中的高效替代方案。

热门栏目