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

兼容API21的GradientDrawable自定义单边边框实现方案咨询

兼容API21的动态单边边框实现方案

方法一:动态构建LayerList(最接近原xml实现逻辑)

原xml通过layer-list的item负边距隐藏部分边框,代码里可动态构建LayerDrawable实现,完全兼容API21:

fun createSingleSideBorderDrawable(
    strokeWidth: Int,
    strokeColor: Int,
    bgColor: Int,
    showLeft: Boolean = true,
    showTop: Boolean = true,
    showRight: Boolean = true,
    showBottom: Boolean = true
): Drawable {
    // 创建基础带边框的shape
    val shape = GradientDrawable().apply {
        shape = GradientDrawable.RECTANGLE
        setStroke(strokeWidth, strokeColor)
        setColor(bgColor)
    }
    // 计算每个方向的负边距:隐藏的边框方向设为负的strokeWidth,显示的方向设为0
    val leftInset = if (showLeft) 0 else -strokeWidth
    val topInset = if (showTop) 0 else -strokeWidth
    val rightInset = if (showRight) 0 else -strokeWidth
    val bottomInset = if (showBottom) 0 else -strokeWidth
    // 包装成LayerDrawable,设置item的insets
    return LayerDrawable(arrayOf(shape)).apply {
        setLayerInset(0, leftInset, topInset, rightInset, bottomInset)
    }
}

使用示例:

// 仅显示顶部和右侧边框
val drawable = createSingleSideBorderDrawable(
    strokeWidth = resources.getDimensionPixelSize(R.dimen.px01),
    strokeColor = ContextCompat.getColor(context, R.color.d7d7d7),
    bgColor = ContextCompat.getColor(context, R.color.white),
    showLeft = false,
    showBottom = false
)
view.background = drawable

方法二:GradientDrawable+透明边框技巧

通过给不需要显示的边框设置透明色,实现单边/部分边框效果,兼容API21:

fun createSingleSideBorderDrawable(
    strokeWidth: Int,
    leftColor: Int,
    topColor: Int,
    rightColor: Int,
    bottomColor: Int,
    bgColor: Int
): GradientDrawable {
    // 创建四个方向的边框drawable,然后叠加
    val layers = mutableListOf<GradientDrawable>()
    
    // 左侧边框
    if (leftColor != Color.TRANSPARENT) {
        layers.add(GradientDrawable().apply {
            shape = GradientDrawable.RECTANGLE
            setColor(leftColor)
            setSize(strokeWidth, GradientDrawable.WRAP_CONTENT)
        })
    }
    // 顶部边框
    if (topColor != Color.TRANSPARENT) {
        layers.add(GradientDrawable().apply {
            shape = GradientDrawable.RECTANGLE
            setColor(topColor)
            setSize(GradientDrawable.WRAP_CONTENT, strokeWidth)
        })
    }
    // 右侧边框
    if (rightColor != Color.TRANSPARENT) {
        layers.add(GradientDrawable().apply {
            shape = GradientDrawable.RECTANGLE
            setColor(rightColor)
            setSize(strokeWidth, GradientDrawable.WRAP_CONTENT)
        })
    }
    // 底部边框
    if (bottomColor != Color.TRANSPARENT) {
        layers.add(GradientDrawable().apply {
            shape = GradientDrawable.RECTANGLE
            setColor(bottomColor)
            setSize(GradientDrawable.WRAP_CONTENT, strokeWidth)
        })
    }
    // 添加背景层
    layers.add(GradientDrawable().apply {
        shape = GradientDrawable.RECTANGLE
        setColor(bgColor)
    })
    
    return LayerDrawable(layers.toTypedArray()).apply {
        // 设置各层的位置
        layers.forEachIndexed { index, drawable ->
            when (index) {
                0 -> setLayerInset(index, 0, 0, bounds.width() - strokeWidth, 0) // 左侧
                1 -> setLayerInset(index, 0, 0, 0, bounds.height() - strokeWidth) // 顶部
                2 -> setLayerInset(index, bounds.width() - strokeWidth, 0, 0, 0) // 右侧
                3 -> setLayerInset(index, 0, bounds.height() - strokeWidth, 0, 0) // 底部
                else -> setLayerInset(index, 0, 0, 0, 0) // 背景
            }
        }
    }
}

使用示例:

val drawable = createSingleSideBorderDrawable(
    strokeWidth = resources.getDimensionPixelSize(R.dimen.px01),
    leftColor = Color.TRANSPARENT,
    topColor = ContextCompat.getColor(context, R.color.d7d7d7),
    rightColor = ContextCompat.getColor(context, R.color.d7d7d7),
    bottomColor = Color.TRANSPARENT,
    bgColor = ContextCompat.getColor(context, R.color.white)
)
view.background = drawable

方法三:View层级模拟(简单场景)

如果是布局层级简单的场景,可通过View的padding和背景色组合模拟边框:

// 给View设置顶部边框
view.apply {
    setBackgroundColor(ContextCompat.getColor(context, R.color.d7d7d7))
    setPadding(0, strokeWidth, 0, 0)
    // 添加内层白色背景View
    val innerView = View(context).apply {
        setBackgroundColor(ContextCompat.getColor(context, R.color.white))
        layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
    }
    (this as ViewGroup).addView(innerView)
}

内容的提问来源于stack exchange,提问作者CodingBruceLee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:42