📝
Jetpack ComposeのTextがEllipsizeされたかを判断する
Android Advent Calendar 2021 12日目
Jetpack Composeは宣言的UIなので、Textのインスタンスを参照して状態を取得することができないのでどうするのか気になって調べた内容になります。
TextLayoutResult
Text
コンポーザブルは、テキストがレイアウトされたときにTextLayoutResult
をコールバックで受け取ることができるonTextLayout
という引数があります。これを使っていきます。
TextLayoutResult
はコンポーザブルをレイアウトした結果を保持しているため、Textを描画したあとのレイアウトの状態を元に何かをするときはだいたいこれを活用することになりそうです。
Ellipsizeされたかを判断する
TextLayoutResult
にisLineEllipsized
メソッドがあるので、これを使うと良さそうです。
Text(
text = "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
maxLines = 2,
overflow = TextOverflow.Ellipsis,
onTextLayout = { result ->
val isEllipsized = result.isLineEllipsized(result.lineCount - 1)
Log.d("Text", "isEllipsized = $isEllipsized")
}
)
EllipsizeされているときにクリックでExpandする
簡易的ですが、クリックでExpandするComposableもこんなふうに作れそうです。
@Composable
fun ExpandableText(
text: String,
modifier: Modifier = Modifier,
maxLines: Int = Int.MAX_VALUE,
overflow: TextOverflow = TextOverflow.Ellipsis,
) {
var isEllipsized by remember { mutableStateOf(false) }
var currentMaxLines by remember { mutableStateOf(maxLines) }
LaunchedEffect(isEllipsized) {
if (!isEllipsized) currentMaxLines = Int.MAX_VALUE
}
Text(
text = text,
modifier = modifier
.clickable(enabled = isEllipsized) { isEllipsized = !isEllipsized }
.animateContentSize(),
maxLines = currentMaxLines,
overflow = overflow,
onTextLayout = { result ->
isEllipsized = result.isLineEllipsized(result.lineCount - 1)
}
)
}
こんなかんじ
Discussion