roh*_*han 19 android kotlin android-jetpack-compose android-jetpack-compose-text
所以我使用Text()像这样的可组合项:
Text(
text = "this is some sample text that is long and so it is
ellipsized",
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Run Code Online (Sandbox Code Playgroud)
并且它正确地省略了文本:
问题是我想要See More在省略号末尾有一个标签,提示用户展开可见的文本框。我该如何添加呢?
Phi*_*hov 20
要解决这个问题,您需要使用onTextLayoutget TextLayoutResult:它包含有关绘制文本状态的所有信息。
使其适用于多行是一项棘手的任务。为此,您需要计算省略号文本和“...查看更多”文本的大小,然后,当您拥有这两个值时,您需要计算需要删除多少文本,以便“...查看更多”完美适合在该行的末尾:
@Composable
fun ExpandableText(
text: String,
modifier: Modifier = Modifier,
minimizedMaxLines: Int = 1,
) {
var cutText by remember(text) { mutableStateOf<String?>(null) }
var expanded by remember { mutableStateOf(false) }
val textLayoutResultState = remember { mutableStateOf<TextLayoutResult?>(null) }
val seeMoreSizeState = remember { mutableStateOf<IntSize?>(null) }
val seeMoreOffsetState = remember { mutableStateOf<Offset?>(null) }
// getting raw values for smart cast
val textLayoutResult = textLayoutResultState.value
val seeMoreSize = seeMoreSizeState.value
val seeMoreOffset = seeMoreOffsetState.value
LaunchedEffect(text, expanded, textLayoutResult, seeMoreSize) {
val lastLineIndex = minimizedMaxLines - 1
if (!expanded && textLayoutResult != null && seeMoreSize != null
&& lastLineIndex + 1 == textLayoutResult.lineCount
&& textLayoutResult.isLineEllipsized(lastLineIndex)
) {
var lastCharIndex = textLayoutResult.getLineEnd(lastLineIndex, visibleEnd = true) + 1
var charRect: Rect
do {
lastCharIndex -= 1
charRect = textLayoutResult.getCursorRect(lastCharIndex)
} while (
charRect.left > textLayoutResult.size.width - seeMoreSize.width
)
seeMoreOffsetState.value = Offset(charRect.left, charRect.bottom - seeMoreSize.height)
cutText = text.substring(startIndex = 0, endIndex = lastCharIndex)
}
}
Box(modifier) {
Text(
text = cutText ?: text,
maxLines = if (expanded) Int.MAX_VALUE else minimizedMaxLines,
overflow = TextOverflow.Ellipsis,
onTextLayout = { textLayoutResultState.value = it },
)
if (!expanded) {
val density = LocalDensity.current
Text(
"... See more",
onTextLayout = { seeMoreSizeState.value = it.size },
modifier = Modifier
.then(
if (seeMoreOffset != null)
Modifier.offset(
x = with(density) { seeMoreOffset.x.toDp() },
y = with(density) { seeMoreOffset.y.toDp() },
)
else
Modifier
)
.clickable {
expanded = true
cutText = null
}
.alpha(if (seeMoreOffset != null) 1f else 0f)
)
}
}
}
Run Code Online (Sandbox Code Playgroud)

ANN*_*NX1 16
我的简单实现,希望有用:
const val DEFAULT_MINIMUM_TEXT_LINE = 3
@Composable
fun ExpandableText(
modifier: Modifier = Modifier,
textModifier: Modifier = Modifier,
style: TextStyle = LocalTextStyle.current,
fontStyle: FontStyle? = null,
text: String,
collapsedMaxLine: Int = DEFAULT_MINIMUM_TEXT_LINE,
showMoreText: String = "... Show More",
showMoreStyle: SpanStyle = SpanStyle(fontWeight = FontWeight.W500),
showLessText: String = " Show Less",
showLessStyle: SpanStyle = showMoreStyle,
textAlign: TextAlign? = null
) {
var isExpanded by remember { mutableStateOf(false) }
var clickable by remember { mutableStateOf(false) }
var lastCharIndex by remember { mutableStateOf(0) }
Box(modifier = Modifier
.clickable(clickable) {
isExpanded = !isExpanded
}
.then(modifier)
) {
Text(
modifier = textModifier
.fillMaxWidth()
.animateContentSize(),
text = buildAnnotatedString {
if (clickable) {
if (isExpanded) {
append(text)
withStyle(style = showLessStyle) { append(showLessText) }
} else {
val adjustText = text.substring(startIndex = 0, endIndex = lastCharIndex)
.dropLast(showMoreText.length)
.dropLastWhile { Character.isWhitespace(it) || it == '.' }
append(adjustText)
withStyle(style = showMoreStyle) { append(showMoreText) }
}
} else {
append(text)
}
},
maxLines = if (isExpanded) Int.MAX_VALUE else collapsedMaxLine,
fontStyle = fontStyle,
onTextLayout = { textLayoutResult ->
if (!isExpanded && textLayoutResult.hasVisualOverflow) {
clickable = true
lastCharIndex = textLayoutResult.getLineEnd(collapsedMaxLine - 1)
}
},
style = style,
textAlign = textAlign
)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10022 次 |
| 最近记录: |