如何将Android drawable XML转换为纯代码实现(含圆角、填充、描边)
1:1 还原目标XML Drawable的代码实现
所有代码内的尺寸参数单位为px,必须先完成dp到px的转换,才能保证显示效果和XML配置一致:
// dp转px工具方法 fun dp2px(dpValue: Float): Int { val density = Resources.getSystem().displayMetrics.density return (dpValue * density + 0.5f).toInt() }
核心实现逻辑如下,可完全复现你提供的XML配置效果:
// 构建圆角矩形shape val shapeDrawable = GradientDrawable().apply { // 指定形状为矩形,对应XML的android:shape="rectangle" shape = GradientDrawable.RECTANGLE // 设置10dp圆角,对应XML的corners配置 cornerRadius = dp2px(10f) // 设置橘色填充,对应XML的solid配置 setColor(ContextCompat.getColor(context, R.color.colorOrange)) // 设置1dp白色描边,对应XML的stroke配置 setStroke(dp2px(1f), Color.WHITE) } // 构建selector结构,对应XML外层的selector标签 val selectorDrawable = StateListDrawable().apply { // 添加无状态的默认条目,对应XML里没有指定状态的item节点 addState(StateSet.WILD_CARD, shapeDrawable) } // 给目标View设置背景 targetView.background = selectorDrawable
如果不需要多状态切换的能力,直接将shapeDrawable设置为目标View的background,视觉效果和原XML编译生成的Drawable完全一致;外层嵌套StateListDrawable只是为了严格还原原XML的selector结构,方便后续拓展不同状态下的Drawable配置。
XML节点与代码类的对应映射
<selector>节点 → 对应 StateListDrawable 类,通过addState()方法添加不同状态下的Drawable条目,和XML里的item节点一一对应<shape android:shape="rectangle">节点 → 对应 GradientDrawable 类,通过shape属性指定矩形/椭圆/线/环形的形状类型<corners android:radius="10dp"/>→ 对应GradientDrawable的cornerRadius属性,若需要单独为四个角设置不同圆角值,可通过cornerRadii数组按顺时针顺序传入每个角的rx、rypx值<solid android:color="@color/colorOrange"/>→ 对应GradientDrawable的setColor()方法,设置纯色填充<stroke android:color="#fff" android:width="1dp"/>→ 对应GradientDrawable的setStroke()方法,传入描边宽度、描边颜色即可实现效果,方法还支持传入虚线宽度、虚线间隙参数实现虚线描边
学习路径建议
- 优先掌握系统封装的高频Drawable子类能力:90%日常开发用到的圆角、填充、描边、状态切换、水波纹、层叠效果,系统已经通过GradientDrawable、StateListDrawable、RippleDrawable、LayerDrawable这几个类做了完整封装,不需要自定义从零实现绘制逻辑
- 对照系统Drawable解析源码熟悉API对应关系:系统内置的DrawableInflater类就是专门把XML配置解析为Drawable实例的核心入口,查看这个类的源码就能看到每个XML标签、属性最终对应的代码调用方法,比零散查文档效率更高
- 自定义Drawable的场景按需拓展:只有遇到需要特殊绘制逻辑(比如复杂的不规则形状、动态变化的绘制效果)时,才需要继承Drawable基类,重写draw、setBounds等方法实现自定义效果,基础UI效果完全可以通过系统封装类快速实现
内容的提问来源于stack exchange,提问作者Charles
相关产品推荐
相关产品推荐

