如何在 Jetpack Compose 中为文本添加 dotted/dashed 下划线?
How do I make a dotted/dashed underline for Text in Jetpack Compose?
我正在尝试获取自定义 TextDecoration - DashUnderline。现有答案仅适用于一行,我需要为每一行文本添加虚线。
对于 TextView,我有一个 class,但我不知道如何将其转换为 Compose。
class DashedUnderlineSpan(
textView: TextView, color: Int, thickness: Float, dashPath: Float,
offsetY: Float, spacingExtra: Float
) :
LineBackgroundSpan, LineHeightSpan {
private val paint: Paint
private val textView: TextView
private val offsetY: Float
private val spacingExtra: Float
override fun chooseHeight(
text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int,
fm: Paint.FontMetricsInt
) {
fm.ascent -= spacingExtra.toInt()
fm.top -= spacingExtra.toInt()
fm.descent += spacingExtra.toInt()
fm.bottom += spacingExtra.toInt()
}
override fun drawBackground(
canvas: Canvas, p: Paint, left: Int, right: Int, top: Int, baseline: Int,
bottom: Int, text: CharSequence, start: Int, end: Int, lnum: Int
) {
val lineNum = textView.lineCount
for (i in 0 until lineNum) {
val layout = textView.layout
val path = android.graphics.Path()
path.moveTo(layout.getLineLeft(i), layout.getLineBottom(i) - spacingExtra + offsetY)
path.lineTo(layout.getLineRight(i), layout.getLineBottom(i) - spacingExtra + offsetY)
canvas.drawPath(path, paint)
}
}
init {
paint = Paint()
paint.color = color
paint.style = Paint.Style.STROKE
paint.pathEffect = DashPathEffect(floatArrayOf(dashPath, dashPath), 0f)
paint.strokeWidth = thickness
this.textView = textView
this.offsetY = offsetY
this.spacingExtra = spacingExtra
}
}
我找到了解决方案:
var layout by remember { mutableStateOf<TextLayoutResult?>(null) }
Text(
text = "История университета",
style = MaterialTheme.typography.h3,
color = Color.Black,
onTextLayout = {
layout = it
},
modifier = Modifier.drawBehind {
layout?.let {
val thickness = 5f
val dashPath = 15f
val spacingExtra = 4f
val offsetY = 6f
for (i in 0 until it.lineCount) {
drawPath(
path = Path().apply {
moveTo(it.getLineLeft(i), it.getLineBottom(i) - spacingExtra + offsetY)
lineTo(it.getLineRight(i), it.getLineBottom(i) - spacingExtra + offsetY)
},
Color.Gray,
style = Stroke(width = thickness,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(dashPath, dashPath), 0f)
)
)
}
}
}
)
我正在尝试获取自定义 TextDecoration - DashUnderline。现有答案仅适用于一行,我需要为每一行文本添加虚线。
对于 TextView,我有一个 class,但我不知道如何将其转换为 Compose。
class DashedUnderlineSpan(
textView: TextView, color: Int, thickness: Float, dashPath: Float,
offsetY: Float, spacingExtra: Float
) :
LineBackgroundSpan, LineHeightSpan {
private val paint: Paint
private val textView: TextView
private val offsetY: Float
private val spacingExtra: Float
override fun chooseHeight(
text: CharSequence, start: Int, end: Int, spanstartv: Int, v: Int,
fm: Paint.FontMetricsInt
) {
fm.ascent -= spacingExtra.toInt()
fm.top -= spacingExtra.toInt()
fm.descent += spacingExtra.toInt()
fm.bottom += spacingExtra.toInt()
}
override fun drawBackground(
canvas: Canvas, p: Paint, left: Int, right: Int, top: Int, baseline: Int,
bottom: Int, text: CharSequence, start: Int, end: Int, lnum: Int
) {
val lineNum = textView.lineCount
for (i in 0 until lineNum) {
val layout = textView.layout
val path = android.graphics.Path()
path.moveTo(layout.getLineLeft(i), layout.getLineBottom(i) - spacingExtra + offsetY)
path.lineTo(layout.getLineRight(i), layout.getLineBottom(i) - spacingExtra + offsetY)
canvas.drawPath(path, paint)
}
}
init {
paint = Paint()
paint.color = color
paint.style = Paint.Style.STROKE
paint.pathEffect = DashPathEffect(floatArrayOf(dashPath, dashPath), 0f)
paint.strokeWidth = thickness
this.textView = textView
this.offsetY = offsetY
this.spacingExtra = spacingExtra
}
}
我找到了解决方案:
var layout by remember { mutableStateOf<TextLayoutResult?>(null) }
Text(
text = "История университета",
style = MaterialTheme.typography.h3,
color = Color.Black,
onTextLayout = {
layout = it
},
modifier = Modifier.drawBehind {
layout?.let {
val thickness = 5f
val dashPath = 15f
val spacingExtra = 4f
val offsetY = 6f
for (i in 0 until it.lineCount) {
drawPath(
path = Path().apply {
moveTo(it.getLineLeft(i), it.getLineBottom(i) - spacingExtra + offsetY)
lineTo(it.getLineRight(i), it.getLineBottom(i) - spacingExtra + offsetY)
},
Color.Gray,
style = Stroke(width = thickness,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(dashPath, dashPath), 0f)
)
)
}
}
}
)