Jetpack中的android:autoSizeTextType撰写

时间:2020-09-19 17:31:38

标签: android kotlin android-jetpack android-jetpack-compose

有没有一种方法可以将文本调整为始终根据固定高度调整大小?

我有一列具有固定高度的列,其中的文本应始终为英尺

 Column(modifier = Modifier.height(150.dp).padding(8.dp)) {
   Text("My really long long long long long text that needs to be resized to the height of this Column")
}

8 个答案:

答案 0 :(得分:6)

这是一个基于@Brian 和@zxon 注释的组合,可根据可用宽度自动调整文本大小。

@Composable
fun AutoSizeText(
    text: String,
    textStyle: TextStyle,
    modifier: Modifier = Modifier
) {
    var scaledTextStyle by remember { mutableStateOf(textStyle) }
    var readyToDraw by remember { mutableStateOf(false) }

    Text(
            text,
            modifier.drawWithContent {
                if (readyToDraw) {
                    drawContent()
                }
            },
            style = scaledTextStyle,
            softWrap = false,
            onTextLayout = { textLayoutResult ->
                if (textLayoutResult.didOverflowWidth) {
                    scaledTextStyle =
                            scaledTextStyle.copy(fontSize = scaledTextStyle.fontSize * 0.9)
                } else {
                    readyToDraw = true
                }
            }
    )
}

预览无法正常工作(至少对于 beta09),您可以添加此代码以使用占位符进行预览:

    if (LocalInspectionMode.current) {
        Text(
                text,
                modifier,
                style = textStyle
        )
        return
    } 

答案 1 :(得分:5)

我使用以下内容根据可用宽度调整字体大小:

val textStyleBody1 = MaterialTheme.typography.body1
val (textStyle, updateTextStyle) = remember { mutableStateOf(textStyleBody1) }
Text(
    text = "long text goes here",
    style = textStyle,
    maxLines = 1,
    softWrap = false,
    onTextLayout = { textLayoutResult ->
        if (textLayoutResult.didOverflowWidth) {
            updateTextStyle(textStyle.copy(fontSize = textStyle.fontSize * 0.9))
        }
    }
)

要根据高度调整字体大小,请使用 Text 组合的属性并使用 didOverflowHeight 而不是 didOverflowWidth

val textStyleBody1 = MaterialTheme.typography.body1
val (textStyle, updateTextStyle) = remember { mutableStateOf(textStyleBody1) }
Text(
    text = "long text goes here",
    style = textStyle,
    overflow = TextOverflow.Clip,
    onTextLayout = { textLayoutResult ->
        if (textLayoutResult.didOverflowHeight) {
            updateTextStyle(textStyle.copy(fontSize = textStyle.fontSize * 0.9))
        }
    }
)

如果您需要在列表中的多个项目之间同步字体大小,请将文本样式保存在可组合函数之外:

private val textStyle = mutableStateOf(MaterialTheme.typography.body1)

@Composable
fun YourComposable() {
    Text(...)
}

这当然不是完美的,因为您会看到文本缩小直到适合为止。对我来说,它工作得很好,因为调整发生在第一个绘制周期内,几乎无法识别。

答案 2 :(得分:1)

尝试 BoxWithConstraints,并学习 SubcomposeLayout 概念

BoxWithConstraints(
    modifier = Modifier
        .fillMaxWidth()
        .weight(5f)
) {
    val size = min(maxWidth * 1.7f, maxHeight)
    val fontSize = size * 0.8f
    Text(
        text = first,
        color = color,
        fontSize = LocalDensity.current.run { fontSize.toSp() },
        modifier = Modifier.fillMaxSize(),
        textAlign = TextAlign.Center,
    )
}

答案 3 :(得分:0)

尝试一下:

const app = express()

var path = __dirname + '/views/'

var router = express.Router()

app.use('/',router)

router.get('/',function(req,res)
{
    res.sendFile(path+'index.html')
}
)

app.listen(3000)

答案 4 :(得分:0)

这是基于穆罕默德的回答。

您必须找到一种通过使用框的高度和消息的长度来计算字体大小的更好方法。

@Composable
fun Greeting() {
    var width by remember { mutableStateOf(0) }
    var height by remember { mutableStateOf(0) }
    val msg = "My really long long long long long text that needs to be resized to the height of this Column"
    Column(modifier = Modifier.height(150.dp).padding(8.dp).background(Color.Blue).onPositioned {
        width = it.size.width
        height = it.size.height
    }) {
        Log.d("mainactivity", "width = $width")
        Log.d("mainactivity", "height = $height")
        Text(
                modifier = Modifier.background(Color.Green).fillMaxHeight(),
                style = TextStyle(fontSize = calculateFontSize(msg, height).sp),
                text = msg
        )
    }
}

fun calculateFontSize(msg: String, height: Int): Int {
    return height / (msg.length / 5)
}

答案 5 :(得分:0)

我想补充一点,如果你不想从@Brian 的回答中看到中间状态,你可以试试这个。

        modifier = Modifier
            .drawWithContent {
                if (calculationFinish) { // replace by your logic 
                    drawContent()
                }
            },

答案 6 :(得分:0)

受@nieto 回答启发的另一种方法是在不重新组合的情况下调整大小,只需在给定入站约束的情况下使用段落块手动测量。还可以正确预览作为奖励



@Composable
fun AutoSizeText(
    text: String,
    style: TextStyle,
    modifier: Modifier = Modifier,
    minTextSize: TextUnit = TextUnit.Unspecified,
    maxLines: Int = Int.MAX_VALUE,
) {
    BoxWithConstraints(modifier) {
        var combinedTextStyle = LocalTextStyle.current + style

        while (shouldShrink(text, combinedTextStyle, minTextSize, maxLines)) {
            combinedTextStyle = combinedTextStyle.copy(fontSize = combinedTextStyle.fontSize * .9f)
        }

        Text(
            text = text,
            style = style + TextStyle(fontSize = combinedTextStyle.fontSize),
            maxLines = maxLines,
        )
    }
}

@Composable
private fun BoxWithConstraintsScope.shouldShrink(
    text: String,
    combinedTextStyle: TextStyle,
    minimumTextSize: TextUnit,
    maxLines: Int
): Boolean = if (minimumTextSize == TextUnit.Unspecified || combinedTextStyle.fontSize > minimumTextSize) {
    false
} else {
    val paragraph = Paragraph(
        text = text,
        style = combinedTextStyle,
        width = maxWidth.value,
        maxLines = maxLines,
        density = LocalDensity.current,
        resourceLoader = LocalFontLoader.current,
    )
    paragraph.height > maxHeight.value
}

答案 7 :(得分:0)

我做了这样的事情

@Composable
fun AutosizeText() {

    var multiplier by remember { mutableStateOf(1f) }

    Text(
        "Some long-ish text",
        maxLines = 1, // modify to fit your need
        overflow = TextOverflow.Visible,
        style = LocalTextStyle.current.copy(
            fontSize = LocalTextStyle.current.fontSize * multiplier
        ),
        onTextLayout = {
            if (it.hasVisualOverflow) {
                multiplier *= 0.99f // you can tune this constant 
            }
        }
    )
}

您可以直观地看到文本缩小到适合