Skip to content

Instantly share code, notes, and snippets.

@inidamleader
Last active September 10, 2024 20:18
Show Gist options
  • Save inidamleader/256bb3e3d5519076fd2c81c2c534f23b to your computer and use it in GitHub Desktop.
Save inidamleader/256bb3e3d5519076fd2c81c2c534f23b to your computer and use it in GitHub Desktop.
UnorderedListText: Composable function that creates a bullet text with the given text
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 = {},
)
}
}
}
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)
}
}
}
}
@inidamleader
Copy link
Author

inidamleader commented Dec 31, 2023

Screenshot from 2024-01-01 11-30-12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment