如何通过代码动态创建双色条纹Drawable?
动态创建双色条纹圆角背景Drawable(Kotlin)
需求说明
需要创建一个作为通用View背景的Drawable,包含两种颜色的矩形条纹(类似旗帜样式),其中一个矩形带有圆角,且颜色需动态设置,无法通过XML定义。
原代码问题分析
你之前的代码存在几个关键问题:
- 错误地给
GradientDrawable设置background属性,应该使用setColor()/setColors()来指定颜色 GradientDrawable的color属性要求传入ColorStateList,单一颜色需通过ColorStateList.valueOf()转换后赋值- 硬编码的固定尺寸(如
100,20)无法适配不同大小的View,需改用动态布局逻辑
正确实现方案
以下是适配View尺寸的动态实现,支持自定义条纹比例和圆角位置:
1. 垂直条纹(上下排列,顶部带圆角)
fun createVerticalBandedBackground( topColor: Int, bottomColor: Int, cornerRadius: Float, topStripRatio: Float = 0.5f // 顶部条纹占总高度的比例,默认50% ): Drawable { // 顶部带圆角的Drawable val topDrawable = GradientDrawable().apply { shape = GradientDrawable.RECTANGLE // 仅设置顶部两个角为圆角 cornerRadii = floatArrayOf( cornerRadius, cornerRadius, cornerRadius, cornerRadius, 0f, 0f, 0f, 0f ) setColor(topColor) } // 底部纯色Drawable val bottomDrawable = GradientDrawable().apply { shape = GradientDrawable.RECTANGLE setColor(bottomColor) } return LayerDrawable(arrayOf(bottomDrawable, topDrawable)).apply { // LayerDrawable子元素顺序为从下到上,所以底部Drawable放在数组首位 // 设置顶部Drawable的内边距,让它只占指定比例的高度 val bottomInsetPercent = (1 - topStripRatio) * 100 setLayerInset(1, 0, 0, 0, bottomInsetPercent.toInt()) gravity = Gravity.TOP } } // 使用示例 view.background = createVerticalBandedBackground( topColor = styles.robotTextBackgroundColor, bottomColor = styles.rootBackground, cornerRadius = 8f, topStripRatio = 0.3f // 顶部条纹占30%高度 )
2. 水平条纹(左右排列,左侧带圆角)
如果需要横向排列的条纹,可调整如下:
fun createHorizontalBandedBackground( leftColor: Int, rightColor: Int, cornerRadius: Float, leftStripRatio: Float = 0.5f ): Drawable { val leftDrawable = GradientDrawable().apply { shape = GradientDrawable.RECTANGLE // 仅设置左侧两个角为圆角 cornerRadii = floatArrayOf( cornerRadius, cornerRadius, 0f, 0f, 0f, 0f, cornerRadius, cornerRadius ) setColor(leftColor) } val rightDrawable = GradientDrawable().apply { shape = GradientDrawable.RECTANGLE setColor(rightColor) } return LayerDrawable(arrayOf(rightDrawable, leftDrawable)).apply { val rightInsetPercent = (1 - leftStripRatio) * 100 setLayerInset(1, 0, 0, rightInsetPercent.toInt(), 0) gravity = Gravity.LEFT } }
关键说明
- LayerDrawable的子Drawable按从下到上的顺序叠加,所以底层的条纹要放在数组前面
- 使用百分比内边距
setLayerInset可以自动适配不同尺寸的View - 如果需要更精确的尺寸控制,可在View的
onMeasure回调中动态计算内边距,或自定义Drawable重写onBoundsChange方法
内容的提问来源于stack exchange,提问作者J. Hill
相关产品推荐
相关产品推荐

