參考這篇文章後的補充。
取得TextLayoutResult的方法有兩種。
第一種:
val textLayoutResultState = remember { mutableStateOf<textlayoutresult>(null) }
Text(
text = text,
style = style,
color = color,
textAlign = textAlign,
onTextLayout = {
textLayoutResultState.value = it
}
)
第二種(style就包含fontSize和color):
val textMeasurer = rememberTextMeasurer()
val textResult = textMeasurer.measure(
text = text,
style = style
)
取得TextLayoutResult後就可以讀取每個字空間大小
text.indices.forEach { index ->
val rect = textLayoutResultState.value!!.getBoundingBox(index)
rectList.add(rect)
}
如果要找特定字串的話可使用這方法
val findText = "find some text"
val startIndex = text.indexOf(findText)
val endIndex = startIndex.plus(findText.length) - 1
(startIndex..endIndex).forEach { index ->
val rect = textLayoutResultState.value!!.getBoundingBox(index)
rectList.add(rect)
}
其中wave path的方法補充(對Path的擴展):
const val TWO_PI = 2 * Math.PI.toFloat()
private fun Path.buildWaveLinePath(bound: Rect, waveLength: Float, animProgress: Float): Path {
asAndroidPath().rewind()
var pointX = bound.left
while (pointX < bound.right) {
val offsetY =
bound.bottom + sin(((pointX - bound.left) / waveLength)
* TWO_PI + (TWO_PI * animProgress)) * 10
if (pointX == bound.left) {
moveTo(bound.left, offsetY)
}
lineTo(pointX, offsetY)
pointX += 1F
}
return this
}
使用wave path的方法:
val infiniteTransition = rememberInfiniteTransition(label = "")
val animProgress = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(500, easing = LinearEasing)
),
label = ""
)
val start = rectList.first()!!.topLeft
val end = rectList.last()!!.bottomRight
val rect = Rect(start, end)
val path = Path().buildWaveLinePath(rect, 50f, animProgress.value)
val pathStyle = Stroke(
width = 5f,
pathEffect = PathEffect.cornerPathEffect(radius = 9.dp.toPx())
)
drawPath(
color = Color.Yellow,
path = path,
style = pathStyle
)