Jetpack compose - Wrong AnnotatedString for Arabic (RTL) punctuation

525 views Asked by At

I'm looking for Arabic notation support in jetpack compose. I want to change the color of some Arabic punctuations and customize their look. Currently, I'm using this function to achieve this:

private fun colorPonctuation(input: String): AnnotatedString {
    return buildAnnotatedString {
        input.forEach {
            if (it == '\u064B' || it == '\u064D'
                || it == '\u064D' || it == '\u064E' || it == '\u064F' ||
                it == '\u0650' || it == '\u0651' || it == '\u0652' || it == '\u0653' ||
                it == '\u0654' || it    == '\u0655' || it == '\u0656' || it == '\u0657' ||
                it == '\u0658' || it == '\u0659' || it == '\u065A' || it == '\u065B' ||
                it == '\u065C' || it == '\u065D' || it == '\u065E' || it == '\u065F' || it == '\u0670'
            ) {
                withStyle(style = SpanStyle(color = Color.Red)) {
                    append(it)
                }
            } else {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append(it)
                }
            }
        }
    }
}

Using this, the Arabic notations and punctuation change their color, but also change their position in the final string which is not what I want.

Here is the full code I'm using:

class Arabic : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        MaterialTheme {
            PreviewArabicText()
        }
    }
}


@Composable
fun ShowArabicText() {
    val str by remember { mutableStateOf(AnnotatedString("بِسْمِ اللهِ الرّحْمنِ الرَّحِیم")) }
    val text by remember { mutableStateOf("بِسْمِ اللهِ الرّحْمنِ الرَّحِیم") }
    var isSelected by remember { mutableStateOf(false) }
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Text(
            text = if (isSelected) colorPonctuation(text) else str,
            color = Color.Blue,
            fontWeight = FontWeight.Bold,
            fontFamily = FontFamily.Default,
            fontStyle = FontStyle.Normal,
            fontSize = 30.sp
        )

        Spacer(modifier = Modifier.width(10.dp))

        Button(onClick = {
            isSelected = !isSelected
        }) {
            Text(text = "change color")
        }
    }

}

Here you can see unwanted position changes for Arabic notations:

Unwaned position changes

0

There are 0 answers