Text の onTextLayout で TextLayoutResult の hasVisualOverflow (didOverflowWidth および didOverflowHeight もある) が true だったら remember {} してる文字サイズを変更するという方法でそれっぽいのは作れるが、State が変わる回数が多い(最終的な textSize と maxTextSize の差が大きい)と文字サイズが変わるアニメーションみたいになってしまうのがつらい。
@Composable
fun AutoSizeableText(
text: String,
maxTextSize: Int = 16,
minTextSize: Int = 14,
modifier: Modifier
) {
var textSize by remember(text) { mutableStateOf(maxTextSize) }
Text(
text = text,
fontSize = textSize.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = modifier,
onTextLayout = {
if (it.hasVisualOverflow && textSize > minTextSize) {
textSize -= 1
}
}
)
}
↑だと1文字増減したときに maxTextSize からやり直しになるので、現在の文字サイズを覚えておいてそこから +/- するようにしたのが ↓
@Composable
fun AutoSizeableText(
text: String,
maxTextSize: Int = 16,
minTextSize: Int = 14,
modifier: Modifier
) {
var textSize by remember { mutableStateOf(maxTextSize) }
val checked = remember(text) { mutableMapOf<Int, Boolean?>() }
var overflow by remember { mutableStateOf(TextOverflow.Clip) }
Text(
text = text,
fontSize = textSize.sp,
maxLines = 1,
overflow = overflow,
modifier = modifier,
onTextLayout = {
if (it.hasVisualOverflow) {
checked[textSize] = true
if (textSize > minTextSize) {
textSize -= 1
} else {
overflow = TextOverflow.Ellipsis
}
} else {
checked[textSize] = false
if (textSize < maxTextSize) {
if (checked[textSize + 1] == null) {
textSize += 1
}
}
}
}
)
}
それでも State が変わる回数が多い(maxTextSize と minTextSize の差が大きくて、一度に長い文字をペーストするとか)と文字サイズが変わるアニメーションみたいになってしまうのがつらいんですよね〜。
0 件のコメント:
コメントを投稿