I want something like this:
• Hey this is my first paragraph.
• Hey this is my second paragraph.
And this is the second line.
• Hey this is my third paragraph.
I want something like this:
• Hey this is my first paragraph.
• Hey this is my second paragraph.
And this is the second line.
• Hey this is my third paragraph.
Found it while brainstorming. Just another approach with annotated string and only one Text.
val bullet = "\u2022"
val messages = listOf(
"Hey This is first paragraph",
"Hey this is my second paragraph. Any this is 2nd line.",
"Hey this is 3rd paragraph."
)
val paragraphStyle = ParagraphStyle(textIndent = TextIndent(restLine = 12.sp))
Text(
buildAnnotatedString {
messages.forEach {
withStyle(style = paragraphStyle) {
append(bullet)
append("\t\t")
append(it)
}
}
}
)
<li>
, <ol>
& <ul>
–
Concur restLine
value rather than using a hardcoded value. The problem with using a hardcoded value, as Arpit Patel has pointed out above, is that it may not work so perfectly on all phones. –
Mitchellmitchem I don't know if it can meet expectations,please try
@Preview(showBackground = true)
@Composable
fun TestList() {
val list = listOf(
"Hey This is first paragraph",
"Hey this is my second paragraph. Any this is 2nd line.",
"Hey this is 3rd paragraph."
)
LazyColumn {
items(list) {
Row(Modifier.padding(8.dp),verticalAlignment = Alignment.CenterVertically) {
Canvas(modifier = Modifier.padding(start = 8.dp,end = 8.dp).size(6.dp)){
drawCircle(Color.Black)
}
Text(text = it,fontSize = 12.sp)
}
}
}
}
Just composed this kind of component
@Composable
fun BulletList(
modifier: Modifier = Modifier,
style: TextStyle,
indent: Dp = 20.dp,
lineSpacing: Dp = 0.dp,
items: List<String>,
) {
Column(modifier = modifier) {
items.forEach {
Row {
Text(
text = "\u2022",
style = style.copy(textAlign = TextAlign.Center),
modifier = Modifier.width(indent),
)
Text(
text = it,
style = style,
modifier = Modifier.weight(1f, fill = true),
)
}
if (lineSpacing > 0.dp && it != items.last()) {
Spacer(modifier = Modifier.height(lineSpacing))
}
}
}
}
Usage
BulletList(
items = listOf(
"First bullet",
"Second bullet ... which is awfully long but that's not a problem",
"Third bullet ",
),
modifier = Modifier.padding(24.dp),
style = MyTheme.typography.body1,
lineSpacing = 8.dp,
)
This answer is based on the accepted answer. I hope it is not redundant. I think it fixes the issue about hardcoding the size of the restLine
by measuring the size of the two tabs instead. We also made it more generic.
@Composable
fun makeBulletedList(items: List<String>): AnnotatedString {
val bulletString = "\u2022\t\t"
val textStyle = LocalTextStyle.current
val textMeasurer = rememberTextMeasurer()
val bulletStringWidth = remember(textStyle, textMeasurer) {
textMeasurer.measure(text = bulletString, style = textStyle).size.width
}
val restLine = with(LocalDensity.current) { bulletStringWidth.toSp() }
val paragraphStyle = ParagraphStyle(textIndent = TextIndent(restLine = restLine))
return buildAnnotatedString {
items.forEach { text ->
withStyle(style = paragraphStyle) {
append(bulletString)
append(text)
}
}
}
}
You can use this function like this:
items = listOf(
"First item",
"Second item is too long to fit in one line, but that's not a problem",
"Third item",
)
Text(text = makeBulletedList(items))
bulletString
value. –
Mitchellmitchem Calculate the correct restLine value
UnorderedListText.kt:
package com.inidamleader.ovtracker.util.compose
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.inidamleader.ovtracker.layer.ui.theme.OvTrackerTheme
import com.inidamleader.ovtracker.util.compose.geometry.toSp
@Composable
fun UnorderedListText(
text: String,
modifier: Modifier = Modifier,
bullet: String = "• ",
highlightedText: String = "",
highlightedTextColor: Color = MaterialTheme.colorScheme.primaryContainer,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
minLines: Int = 1,
onTextLayout: (TextLayoutResult) -> Unit = {},
style: TextStyle = LocalTextStyle.current,
) {
val restLine = run {
val textMeasurer = rememberTextMeasurer()
remember(key1 = bullet, key2 = style) {
textMeasurer.measure(text = bullet, style = style).size.width
}.toSp
}
Text(
text = remember(
text,
bullet,
restLine,
highlightedText,
highlightedTextColor,
) {
text.unorderedListAnnotatedString(
bullet = bullet,
restLine = restLine,
highlightedText = highlightedText,
highlightedTxtColor = highlightedTextColor,
)
},
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
minLines = minLines,
onTextLayout = onTextLayout,
style = style,
modifier = modifier,
)
}
@Preview
@Composable
fun PreviewUnorderedListText() {
OvTrackerTheme {
Surface {
UnorderedListText(
text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit." +
"\nEtiam lipsums et metus vel mauris scelerisque molestie eget nec ligula." +
"\nNulla scelerisque, magna id aliquam rhoncus, ipsumx turpis risus sodales mi, sit ipsum amet malesuada nibh lacus sit amet libero." +
"\nCras in sem euismod, vulputate ligula in, egestas enim ipsum.",
modifier = Modifier.padding(8.dp),
highlightedText = "ipsum",
overflow = TextOverflow.Ellipsis,
onTextLayout = {},
)
}
}
}
StringExt.kt:
package com.inidamleader.ovtracker.util.compose
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.ParagraphStyle
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextIndent
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
fun String.unorderedListAnnotatedString(
bullet: String = "• ",
restLine: TextUnit = 12.sp,
highlightedText: String = "",
highlightedTxtColor: Color = Color.Cyan,
) = buildAnnotatedString {
split("\n").forEach {
var txt = it.trim()
if (txt.isNotBlank()) {
withStyle(style = ParagraphStyle(textIndent = TextIndent(restLine = restLine))) {
append(bullet)
if (highlightedText.isNotEmpty()) {
while (true) {
val i = txt.indexOf(string = highlightedText, ignoreCase = true)
if (i == -1) break
append(txt.subSequence(startIndex = 0, endIndex = i).toString())
val j = i + highlightedText.length
withStyle(style = SpanStyle(background = highlightedTxtColor)) {
append(txt.subSequence(startIndex = i, endIndex = j).toString())
}
txt = txt.subSequence(startIndex = j, endIndex = txt.length).toString()
}
}
append(txt)
}
}
}
}
© 2022 - 2024 — McMap. All rights reserved.