Jetpack compose 在文本中显示 html
Jetpack compose display html in text
我有一个包含 html 的字符串,如何在 Jetpack 撰写文本中显示它?
在 TextView 中,我会使用 Spanned 并执行如下操作:
TextView.setText(Html.fromHtml("<p>something", HtmlCompat.FROM_HTML_MODE_LEGACY)
如何使用 Jetpack compose 中的文本执行此操作?
遗憾的是,Jetpack compose 尚不支持 HTML...
那么,您可以做的是:
选项 1:创建您自己的 HTML 解析器
Jetpack compose 支持基本样式,例如粗体、颜色、字体等。因此您可以做的是遍历原始 HTML 文本并手动应用文本样式。
选项 2:将旧的 TextView
集成到您的 Jetpack compose 中。
请阅读:Adopting Compose in your app
谢谢。
您可以将旧的 TextView 集成到您的 Jetpack compose 中,如下所示:
AndroidView(factory = { context ->
TextView(context).apply {
text = Html.fromHtml(your_html)
}
})
更多信息:https://foso.github.io/Jetpack-Compose-Playground/viewinterop/androidview/
与 Yhondri 的答案相同,但如果您的目标是 api >24:
,则使用 HtmlCompat
@Composable
fun Html(text: String) {
AndroidView(factory = { context ->
TextView(context).apply {
setText(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY))
}
})
}
我已经这样做了,而不是在 AndroidView 中使用 TextView,它对我来说似乎工作得很好。下面的可组合项还会包裹文本并在您单击它时展开。
@Composable
fun ExpandingText(
description: String,
modifier: Modifier = Modifier,
textStyle: TextStyle = MaterialTheme.typography.body2,
expandable: Boolean = true,
collapsedMaxLines: Int = 3,
expandedMaxLines: Int = Int.MAX_VALUE,
) {
val text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(description, Html.FROM_HTML_MODE_LEGACY)
} else {
HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
var canTextExpand by remember(text) { mutableStateOf(true) }
var expanded by remember { mutableStateOf(false) }
val interactionSource = remember { MutableInteractionSource() }
Text(
text = text.toString(),
style = textStyle,
overflow = TextOverflow.Ellipsis,
maxLines = if (expanded) expandedMaxLines else collapsedMaxLines,
modifier = Modifier
.clickable(
enabled = expandable && canTextExpand,
onClick = { expanded = !expanded },
indication = rememberRipple(bounded = true),
interactionSource = interactionSource,
)
.animateContentSize(animationSpec = spring())
.then(modifier),
onTextLayout = {
if (!expanded) {
canTextExpand = it.hasVisualOverflow
}
}
)
}
我有一个包含 html 的字符串,如何在 Jetpack 撰写文本中显示它?
在 TextView 中,我会使用 Spanned 并执行如下操作:
TextView.setText(Html.fromHtml("<p>something", HtmlCompat.FROM_HTML_MODE_LEGACY)
如何使用 Jetpack compose 中的文本执行此操作?
遗憾的是,Jetpack compose 尚不支持 HTML...
那么,您可以做的是:
选项 1:创建您自己的 HTML 解析器
Jetpack compose 支持基本样式,例如粗体、颜色、字体等。因此您可以做的是遍历原始 HTML 文本并手动应用文本样式。
选项 2:将旧的 TextView
集成到您的 Jetpack compose 中。
请阅读:Adopting Compose in your app
谢谢。
您可以将旧的 TextView 集成到您的 Jetpack compose 中,如下所示:
AndroidView(factory = { context ->
TextView(context).apply {
text = Html.fromHtml(your_html)
}
})
更多信息:https://foso.github.io/Jetpack-Compose-Playground/viewinterop/androidview/
与 Yhondri 的答案相同,但如果您的目标是 api >24:
,则使用 HtmlCompat@Composable
fun Html(text: String) {
AndroidView(factory = { context ->
TextView(context).apply {
setText(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY))
}
})
}
我已经这样做了,而不是在 AndroidView 中使用 TextView,它对我来说似乎工作得很好。下面的可组合项还会包裹文本并在您单击它时展开。
@Composable
fun ExpandingText(
description: String,
modifier: Modifier = Modifier,
textStyle: TextStyle = MaterialTheme.typography.body2,
expandable: Boolean = true,
collapsedMaxLines: Int = 3,
expandedMaxLines: Int = Int.MAX_VALUE,
) {
val text = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(description, Html.FROM_HTML_MODE_LEGACY)
} else {
HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
var canTextExpand by remember(text) { mutableStateOf(true) }
var expanded by remember { mutableStateOf(false) }
val interactionSource = remember { MutableInteractionSource() }
Text(
text = text.toString(),
style = textStyle,
overflow = TextOverflow.Ellipsis,
maxLines = if (expanded) expandedMaxLines else collapsedMaxLines,
modifier = Modifier
.clickable(
enabled = expandable && canTextExpand,
onClick = { expanded = !expanded },
indication = rememberRipple(bounded = true),
interactionSource = interactionSource,
)
.animateContentSize(animationSpec = spring())
.then(modifier),
onTextLayout = {
if (!expanded) {
canTextExpand = it.hasVisualOverflow
}
}
)
}