XML Shape/Selector → Kotlin 动态创建

XML Shape/Selector → Kotlin 动态创建

老写法(XML drawable)

res/drawable/bg_rounded_button.xml:

xml 复制代码
<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:

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 中使用:

java 复制代码
view.setBackgroundResource(R.drawable.selector_button);

问题在哪里

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

新写法(Kotlin 动态创建)

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

使用:

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

一句话注意

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


Java Android 老项目迁移系列,持续更新中。

相关推荐
youdexiang7 小时前
Android录音软件时间关键词检索功能分析
java·人工智能
sunshine22 girl7 小时前
Java学习七 Java 项目实战1-项目创建和主页面搭建
java·开发语言·学习
code2cat7 小时前
Java进阶篇之AtomicStampedReference:引用回到原值,版本戳仍能记住变化
java·cas·并发编程·aba
熊猫钓鱼>_>8 小时前
Kotlin Multiplatform for OpenHarmony 实战:为 KMPNotifier 实现 OpenHarmony 本地通知引擎
kotlin·ai编程·harmonyos·鸿蒙·openharmony·适配·kmp
泡茶喝茶写代码9 小时前
A股量化数据工程:从 REST 接口到策略信号(第 8 篇):成长能力因子:营收与利润增速
java·python·股票数据api·股票数据api接口·股票量化数据api·股票量化数据接口·股票数据api数据
三少爷的鞋9 小时前
AI 时代,我们都将成为通才型开发者:只懂 Android,已经不够了
android
\光辉岁月/10 小时前
7.javase-面向对象
java·开发语言
weixin_5310946910 小时前
heap_4内存管理
java·开发语言·算法
程序员南飞10 小时前
win系统安装minio
java·数据结构·算法
Escalating_xu11 小时前
【Python】使用库:标准库、第三方库、pip、项目实战与程序打包
java·python·pip