Android如何实现仅覆盖文字区域的多行TextView背景效果
实现多行文字背景仅覆盖内容区域的TextView方案
以下提供三种适配不同场景的实现方式:
方案1:自定义TextView(传统View体系通用方案)
重写TextView的onDraw方法,逐行计算文字实际占据的宽度,绘制对应范围的背景即可,适配任意多行场景:
class LineBackgroundTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AppCompatTextView(context, attrs, defStyleAttr) { private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { color = Color.YELLOW // 可自定义背景色 } private val cornerRadius = 4f.dp // 可自定义圆角大小,dp转px的扩展方法自行实现即可 private val verticalPadding = 2f.dp // 文字上下的背景边距 private val horizontalPadding = 4f.dp // 文字左右的背景边距 override fun onDraw(canvas: Canvas) { val layout = layout ?: return super.onDraw(canvas) // 遍历每一行文字 for (i in 0 until lineCount) { val lineLeft = layout.getLineLeft(i) + horizontalPadding val lineRight = layout.getLineRight(i) - horizontalPadding val lineTop = layout.getLineTop(i) + verticalPadding val lineBottom = layout.getLineBottom(i) - verticalPadding // 绘制圆角背景 canvas.drawRoundRect( lineLeft, lineTop, lineRight, lineBottom, cornerRadius, cornerRadius, backgroundPaint ) } super.onDraw(canvas) } }
方案2:SpannableString实现(适合动态文本/局部背景场景)
如果不需要全局给整个TextView加背景,仅需要给部分文本加背景,可以用自定义Span实现:
class RoundBackgroundColorSpan( private val bgColor: Int, private val textColor: Int, private val cornerRadius: Float, private val paddingHorizontal: Float, private val paddingVertical: Float ) : ReplacementSpan() { override fun getSize(paint: Paint, text: CharSequence?, start: Int, end: Int, fm: Paint.FontMetricsInt?): Int { return (paint.measureText(text, start, end) + paddingHorizontal * 2).toInt() } override fun draw(canvas: Canvas, text: CharSequence?, start: Int, end: Int, x: Float, top: Int, y: Int, bottom: Int, paint: Paint) { val textWidth = paint.measureText(text, start, end) // 绘制背景 paint.color = bgColor canvas.drawRoundRect( x, top.toFloat() + paddingVertical, x + textWidth + paddingHorizontal * 2, bottom.toFloat() - paddingVertical, cornerRadius, cornerRadius, paint ) // 绘制文字 paint.color = textColor canvas.drawText(text!!, start, end, x + paddingHorizontal, y.toFloat(), paint) } }
使用时直接给Spannable设置对应Span即可。
方案3:Jetpack Compose实现
如果项目已经接入Jetpack Compose,无需自定义,直接使用Text组件的background修饰符即可自动适配多行文字的背景范围:
Text( text = "你的多行文本内容", modifier = Modifier .background( color = Color.Yellow, shape = RoundedCornerShape(4.dp) ) .padding(horizontal = 4.dp, vertical = 2.dp) )
内容的提问来源于stack exchange,提问作者Mousa
相关产品推荐
相关产品推荐

