You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码动态创建双色条纹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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:57:45