Jetpack compose AutoSizeText

526 阅读1分钟
image.png

在TextView中使用app:autoSizeTextType="uniform"就可以实现。

我参考了这一篇# android:autoSizeTextType in Jetpack Compose 写了一个我自己实现的MyAutoSizeText:

@Composable
fun MyAutoSizeText(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Visible,
    softWrap: Boolean = true,
    maxLines: Int = 1,
    style: TextStyle = LocalTextStyle.current,
    fontList: Array<TextUnit>,
) {
    BoxWithConstraints(modifier) {
        val localDensity = LocalDensity.current
        SubcomposeLayout{ constraints ->
          Log.i("hj","width = ${maxWidth}")

            val index = subcompose("text") {
                fontList.forEach {
                    Text(
                        text = text,
                        color = color,
                        maxLines = maxLines,
                        fontStyle = fontStyle,
                        fontWeight = fontWeight,
                        fontFamily = fontFamily,
                        letterSpacing = letterSpacing,
                        textDecoration = textDecoration,
                        textAlign = textAlign,
                        lineHeight = lineHeight,
                        overflow = overflow,
                        softWrap = softWrap,
                        style = style.copy(fontSize = it))
                }
            }.indexOfFirst {
                val placeable = it.measure(constraints.copy(maxWidth = Int.MAX_VALUE))
                placeable.width <= with(localDensity){maxWidth.toPx()}
            }

            val textSize = if (index >= 0) {
                fontList[index]
            } else {
                fontList.minOf { it.value }.toSp()
            }

            Log.i("hj","textSize = ${textSize}")

            val contentPlaceable = subcompose("content") {
                Text(
                    modifier = modifier,
                    text = text,
                    color = color,
                    maxLines = maxLines,
                    fontStyle = fontStyle,
                    fontWeight = fontWeight,
                    fontFamily = fontFamily,
                    letterSpacing = letterSpacing,
                    textDecoration = textDecoration,
                    textAlign = textAlign,
                    lineHeight = lineHeight,
                    overflow = overflow,
                    softWrap = softWrap,
                    style = style.copy(fontSize = textSize))
            }[0].measure(constraints)

            layout(contentPlaceable.width, contentPlaceable.height) {
                contentPlaceable.place(0, 0)
            }
        }
    }
}

BoxWithConstraints 是用来得到组合项的宽度的:maxWidth。

val index = subcompose("text") {
                fontList.forEach {
                    Text(...)
                }
            }.indexOfFirst {
                val placeable = it.measure(constraints.copy(maxWidth = Int.MAX_VALUE))
                placeable.width <= with(localDensity){maxWidth.toPx()}
            }

这里是用于测量得到fontList里面满足条件的fontSize

 val textSize = if (index >= 0) {
                fontList[index]
            } else {
                fontList.minOf { it.value }.toSp()
            }

最后得到调整后的textSize

使用:

MyAutoSizeText(text = "888888",
    fontList = arrayOf(28.sp, 25.sp, 22.sp, 20.sp, 18.sp, 15.sp, 12.sp, 10.sp),
    modifier = Modifier.width(50.dp))