兼容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
相关产品推荐
相关产品推荐

