參考這篇文章後的補充。
取得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 )