项目需求中有时可能需要显示弯曲弧形的文本,比如文字要显示为印章样式,则需要将文字沿弧形路径显示,本文介绍 Android 中如何使用 Jetpack Compose 实现沿着弧形路径排版类似印章的文字效果。
印章样式的文字效果
如下图的效果:
代码:
@Composable
fun SealStyleCurvedText() {
val textMeasurer = rememberTextMeasurer()
val icLauncher = getAppIconBitmap(LocalContext.current)?.asImageBitmap()
Canvas(
Modifier
.padding(16.dp)
.size(300.dp),
) {
// 绘制红色圆形
drawCircle(
color = Color.Red,
radius = 150.dp.toPx(),
center = Offset(150.dp.toPx(), 150.dp.toPx()),
style = Stroke(4.dp.toPx()),
)
// 绘制弧形布局的文字,并在上方居中
drawIntoCanvas {
val path = android.graphics.Path().apply {
addArc(
RectF(36.dp.toPx(), 36.dp.toPx(), 264.dp.toPx(), 264.dp.toPx()),
90F,
359.9F,
)
}
it.nativeCanvas.drawTextOnPath(
"Hello itmob.cn! Hello Jetpack Compose!",
path,
0f,
0f,
android.graphics.Paint().apply {
textSize = 24.sp.toPx()
textAlign = android.graphics.Paint.Align.CENTER
},
)
}
// 绘制底部文字
drawText(
textMeasurer = textMeasurer,
text = buildAnnotatedString {
withStyle(
style = ParagraphStyle(textAlign = TextAlign.Center),
) {
withStyle(
style = SpanStyle(
color = Color.Black,
fontSize = 26.sp,
fontWeight = FontWeight.Bold,
),
) {
append("https://itmob.cn")
}
}
},
topLeft = Offset.Zero.copy(y = 216.dp.toPx()),
size = size,
)
// 绘制中间的应用图标
icLauncher?.let {
drawImage(
image = it,
topLeft = Offset(x = size.width/2-it.width/2, y = size.height/2-it.height/2),
)
}
}
}
绘制沿弧形路径显示的文本使用的是 drawIntoCanvas
方法,而不是 Compose 提供的原生 API,因为当前版本(1.4.3)的 Jetpack Compose 还为提供 drawTextOnPath
类似的方法。
注意
细心的朋友可能留意到了在绘制圆弧时的代码:
val path = android.graphics.Path().apply {
addArc(
RectF(36.dp.toPx(), 36.dp.toPx(), 264.dp.toPx(), 264.dp.toPx()),
90F,
359.9F,
)
}
代码中 addArc 方法的 sweepAngle
参数是 359.9F,而不是 360F,这是因为在 Android 5.0 API 21 中如果 sweepAngle
参数是 360 度,绘制图像时起始角度又变为了 0 度,这在绘制圆弧时可能并没有影响,但是我们需要让文字居中显示,就需要使圆弧路径的起始角度为 90 度,并让文字在路径中居中来实现。
所以 sweepAngle
使用了 359.9 而不是 360 度。
sweepAngle 为 360 度时,addArc 方法的 startAngle 参数不起作用
val path = android.graphics.Path().apply {
addArc(
RectF(36.dp.toPx(), 36.dp.toPx(), 264.dp.toPx(), 264.dp.toPx()),
90F,
360F,
)
}
其他
更多关于 Jetpack Compose 文本的介绍:
Jetpack Compose 中 DrawStyle 详解 - (线段/笔画/轮廓的绘制样式)
Jetpack Compose 中如何自定义文本笔画的描边效果
Jetpack Compose 中怎样隐藏或禁用 TextField(文本字段)的光标、文本选择手柄和文本工具栏?
怎样处理 Jetpack Compose 中文本的长按选择和点击事件(如何在 Text 中添加超链接?)
Jetpack Compose TextField VisualTransformation 视觉转换详解-高亮显示URL-格式化显示银行卡号码
怎样处理 Jetpack Compose 中文本的长按选择和点击事件(如何在 Text 中添加超链接?)
Jetpack Compose 怎样实现跑马灯效果(Marquee)
在 Jetpack Compose 中使用 DrawScope.drawText API 将文本绘制到 Canvas 上