android 如何使用Jetpack编写Telegram或WhatsApp等文本,将多个子字符串的粗体字符 Package 在一个模式中

von4xj4u  于 2023-03-16  发布在  Android
关注(0)|答案(2)|浏览(170)

我的目标是创建一个粗体文本时,字符串中的一些单词或字符 Package 特殊字符,如粗体显示为粗体与Jetpack合成Text组件多次在特定字符串中可用。

val boldRegex = Regex("\\*\\*.*\\*\\*")

使用这个正则表达式和下面的代码段

@Composable
fun CustomText(text: String, modifier: Modifier = Modifier) {

    val boldKeywords: MatchResult? = boldRegex.find(text)

    val boldIndexes = mutableListOf<Pair<Int, Int>>()
    boldKeywords?.let {
        boldIndexes.add(Pair(it.range.first, it.range.last - 2))
    }

    val newText = text.replace("**", "")

    val annotatedString = buildAnnotatedString {
        append(newText)

        // Add bold style to keywords that has to be bold
        boldIndexes.forEach {
            addStyle(
                style = SpanStyle(
                    fontWeight = FontWeight.Bold,
                    color = Color(0xff64B5F6),
                    fontSize = 15.sp

                ),
                start = it.first,
                end = it.second
            )

        }
    }

    Text(
        modifier = modifier
            .fillMaxWidth()
            .padding(start = 8.dp, end = 8.dp, top = 12.dp, bottom = 12.dp),
        fontSize = 16.sp,
        text = annotatedString
    )
}

只有当一个确切的模式存在一次时,我才能得到正确的结果,而且替换字符的每一次出现也是不正确的。

CustomText(text = "This is a **bold** text")

CustomText(
    text = "This is a **bold** text  and another **random** value build with *regex expression"
)

CustomText(
    text = "This is NOT a ****bold** text build with *regex expression"
)

CustomText(
    text = "This is NOT a **bold text build with *regex expression"
)
  • 在第一个文本中,结果符合预期
  • 在第二个中,它应该只将boldrandom子字符串设置为粗体
  • 在第三个中,它不应该有任何粗体子字符串,也不应该有替换
  • 在第四个字符串中,不应该有粗体子字符串和替换

我检查了这个regex question,但是我无法找到正确的正则表达式来分组并将pattern替换为

6za6bjd0

6za6bjd01#

感谢@Wiktor Stribizew对regex的帮助,我想出了一个解决方案,但我不认为它像我期望的那样有效。如果你想出了更好的解决方案,请随时添加新的答案。

val boldRegex = Regex("(?<!\\*)\\*\\*(?!\\*).*?(?<!\\*)\\*\\*(?!\\*)")

@Composable
fun CustomText(text: String, modifier: Modifier = Modifier) {

    var results: MatchResult? = boldRegex.find(text)

    val boldIndexes = mutableListOf<Pair<Int, Int>>()

    val keywords = mutableListOf<String>()

    var finalText = text

    while (results != null) {
        keywords.add(results.value)
        results = results.next()
    }

    keywords.forEach { keyword ->
        val indexOf = finalText.indexOf(keyword)
        val newKeyWord = keyword.removeSurrounding("**")
        finalText = finalText.replace(keyword, newKeyWord)
        boldIndexes.add(Pair(indexOf, indexOf + newKeyWord.length))
    }

    val annotatedString = buildAnnotatedString {
        append(finalText)

        // Add bold style to keywords that has to be bold
        boldIndexes.forEach {
            addStyle(
                style = SpanStyle(
                    fontWeight = FontWeight.Bold,
                    color = Color(0xff64B5F6),
                    fontSize = 15.sp

                ),
                start = it.first,
                end = it.second
            )

        }
    }

    Text(
        modifier = modifier
            .fillMaxWidth()
            .padding(start = 8.dp, end = 8.dp, top = 12.dp, bottom = 12.dp),
        fontSize = 16.sp,
        text = annotatedString
    )
}

我认为它可以解决不使用第二个循环,但找不到它。
结果

Column() {
    CustomText(text = "This is a **bold** text")

    CustomText(
        text = "This is a **bold** text and another **random** value **build** with *regex expression"
    )

    CustomText(
        text = "This is NOT a ****bold** text build with *regex expression"
    )

    CustomText(
        text = "This is NOT a **bold text build with *regex expression"
    )
}

dy1byipe

dy1byipe2#

我用更少的代码和for循环对你的答案做了一些修改,你可以检查一下

val boldRegex = Regex("(?<!\\*)\\*\\*(?!\\*).*?(?<!\\*)\\*\\*(?!\\*)")

@Composable
fun TextWithBoldStrings(
    modifier: Modifier = Modifier,
    text: String,
    regularFontSize: TextUnit = 16.sp,
    boldSpanStyle: SpanStyle = SpanStyle(
        fontWeight = FontWeight.Bold,
        color = Color(0xff64B5F6),
        fontSize = 15.sp
    )
) {

    val keywords = boldRegex.findAll(text).map { it.value }.toList()

    val annotatedString = buildAnnotatedString {
        var startIndex = 0
        keywords.forEach { keyword ->
            val indexOf = text.indexOf(keyword)
            append(text.substring(startIndex, indexOf))
            startIndex = indexOf + keyword.length
            val newKeyWord = keyword.removeSurrounding("**")
            withStyle(
                style = boldSpanStyle
            ) {
                append(newKeyWord)
            }
        }
        append(text.substring(startIndex, text.length))

    }

    Text(
        modifier = modifier,
        fontSize = regularFontSize,
        text = annotatedString
    )
}

相关问题