Skip to content

Text changes do not offer full support for all characters in Compose #2703

@ninavandijkk

Description

@ninavandijkk

Is your feature request related to a problem? Please describe.
I'm having troubles with dynamically changing all texts of my json animations in Lottie Compose. Within our app we are using the old TextDelegate way to change the texts in animations to the users language by getting the keys we put in the animations. The current implemented way with dynamic properties doesn't work for us, since we need to change all text values and only the characters that were previously in the value will be displayed. For us this is a problem since our keys do not contain all the characters of the text the key needs to be changed to.

Describe the solution you'd like
I would like a fitted approach for having multilingual animations and text changes not only displaying characters that were in the previous value.

Describe alternatives you've considered
We both tried to use the dynamic properties and directly alter the json file through some sort of TextDelegate implementation. With both implementations only the characters that were in the values before the text was altered were displayed.

Additional context
With the current implementation this is the result we are getting:
Image

The implementation we have for displaying the animation is as followed:

val jsonString = LocalizedText().modifyLottieJson(tutorialStep.image)

val composition by rememberLottieComposition(
    spec = LottieCompositionSpec.JsonString(jsonString)
)
LottieAnimation(
    composition = composition,
    iterations = LottieConstants.IterateForever,
)

LocalizedText we use to change the texts:

class LocalizedText {
    @SuppressLint("LocalContextResourcesRead")
    @Composable
    fun modifyLottieJson(
        lottieJsonId: Int
    ): String {
        val context = LocalContext.current
        val inputStream = context.resources.openRawResource(lottieJsonId)
        val jsonString = inputStream.bufferedReader().use { it.readText() }

        val jsonObject = JSONObject(jsonString)
        val layersArray = jsonObject.getJSONArray("layers")
        for (i in 0 until layersArray.length()) {
            val layer = layersArray.getJSONObject(i)
            if (layer.getInt("ty") == 5 && layer.has("t")) { // Text layer
                val textObject = layer.getJSONObject("t")
                if (textObject.has("d")) {
                    val dObject = textObject.getJSONObject("d")
                    if (dObject.has("k")) {
                        val textValue = dObject.getJSONArray("k")
                        for (j in 0 until textValue.length()) {
                            val textItem = textValue.getJSONObject(j)
                            if (textItem.has("s")) {
                                val styleObject = textItem.getJSONObject("s")
                                val value = styleObject.getString("t")
                                    .replace(DOT, UNDERSCORE)
                                    .replace("\r", "")
                                    .lowercase()
                                val stringId = context.resources.getIdentifier(
                                    value,
                                    RES_TYPE_STRING,
                                    context.packageName
                                )
                                val translation = context.getText(stringId)
                                styleObject.put("t", translation)
                                textItem.put("s", styleObject)
                            }
                        }
                    }
                }
            }
        }
        return jsonObject.toString()
    }

    companion object {
        private const val RES_TYPE_STRING = "string"
        private const val UNDERSCORE = "_"
        private const val DOT = "."
    }
}

Example of our pre-modified json Lottie animation:

tutorial_count_page10.json

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions