I have a description text which is long. I'm trying to implement expand/collapse feature for the text. For the feature, I just refer to https://stackoverflow.com/a/68894858/11943929.
So here is what I've done so far:
private const val MINIMIZED_MAX_LINES = 5
@Composable
fun ProductDescription(
modifier: Modifier = Modifier,
description: String? = null
) {
var expanded by rememberSaveable { mutableStateOf(false) }
val textLayoutResultState = remember { mutableStateOf<TextLayoutResult?>(null) }
val seeMoreSizeState = remember { mutableStateOf<IntSize?>(null) }
val seeMoreOffsetState = remember { mutableStateOf<Offset?>(null) }
val textLayoutResult = textLayoutResultState.value
val seeMoreSize = seeMoreSizeState.value
val seeMoreOffset = seeMoreOffsetState.value
description?.let {
val productDesc = Jsoup
.parse(it)
.wholeText()
.replace("\\s+--\\s\\s".toRegex(), "\n\n")
.replace("\\s{3,}".toRegex(), "\n\n")
.replace("\\n+X".toRegex(), " X")
.trim()
var cutText by remember { mutableStateOf<String?>(null) }
LaunchedEffect(productDesc, expanded, textLayoutResult, seeMoreSize) {
val lastLineIndex = MINIMIZED_MAX_LINES - 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 = productDesc.substring(startIndex = 0, endIndex = lastCharIndex)
}
}
Column(
modifier = modifier,
verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.dimen_8))
) {
Box {
Text(
text = cutText ?: productDesc,
maxLines = if (expanded) Int.MAX_VALUE else MINIMIZED_MAX_LINES,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.h4,
onTextLayout = { textLayoutResultState.value = it },
color = RubiBrandsTheme.colors.productDetailsDescriptionColor,
)
if (!expanded) {
val density = LocalDensity.current
Text(
text = stringResource(id = R.string.show_more),
fontWeight = FontWeight.SemiBold,
onTextLayout = { seeMoreSizeState.value = it.size },
color = RubiBrandsTheme.colors.textLink,
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)
)
}
}
if (expanded) {
Text(
text = stringResource(id = R.string.show_less),
fontWeight = FontWeight.SemiBold,
color = RubiBrandsTheme.colors.textLink,
modifier = Modifier
.clickable {
expanded = false
}
)
}
}
}
}
This code works as intended except for one case.
The case is if the last line of the cutted text is a blank line the See More button is not showing up. Here is what I mean :
Otherwise, it is working:
I am also adding the text that causing the issue if you want to test:
Micro fiber top layer
Comfortable for sweating classes
Machine washable
Special Asian flowers design
173cmx62cmx3mm
Asian Flowers
from Jetpack Compose: See More button is not showing up for the expandable text when the last line of the collapsed text is blank
No comments:
Post a Comment