Search code examples
androidandroid-jetpack-composekotlin-multiplatformcompose-multiplatform

Multiplatform Compose state does not update font change in Text on Android (on IOS it works well)


we are working on some kind of reader experience for the users. We are trying to allow the user to change font size, color, etc. One of the options is to change the font completely.

What we faced, is that it does not work on Android (well maybe kind of does), but works well on iOS. The whole example project can be found here -> https://github.com/fandomWojtek/Test_ReaderApp

We use Compose Multiplatform 1.6.10, Kotlin 2.0.0, Compose Resources

And now to the point -> we have a mutable state of Text Style

    data class Style(val color: Color = Color.Black, val fontSize: Float = 14f, val fontFamily: FontResource = Res.font.rubik_regular)
    
    
    @Composable
    fun TestScreen() {
        var styleState by remember {
            mutableStateOf(Style())
        }
        Column(modifier = Modifier.background(Color.White)) {
            LazyColumn(modifier = Modifier.weight(1.0f), verticalArrangement = Arrangement.spacedBy(24.dp)) {
                for (i in 0..100) {
                    item {
                        Text(
                            staticText,
                            style = style.copy(color = styleState.color, fontSize = styleState.fontSize.sp, fontFamily = FontFamily(Font(styleState.fontFamily, FontWeight.Normal)))
                            )
                    }
                }
            }
           //Some code removed to readability
            Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
                Text(
                    modifier = Modifier.padding(16.dp).clickable {
                        styleState = (styleState.copy(fontFamily = Res.font.rubik_regular))
                    },
                    text = "roboto",
                    style = style
                )
    
                Text(
                    modifier = Modifier.padding(16.dp).clickable {
                        styleState = (styleState.copy(fontFamily = Res.font.HelveticaNeueMedium))
                    },
                    text = "helvetica",
                    style = style
                )
    
                Text(
                    modifier = Modifier.padding(16.dp).clickable {
                        styleState = (styleState.copy(fontFamily = Res.font.COMICSANS))
                    },
                    text = "Comic Sans",
                    style = style
                )
            }
        }
    }

And to our surprise, it does not work on Android, the Text is doing a recomposition, but it does not update on the screen (when you scroll Text out of the screen and then scroll back, it has a new Font)

enter image description here

What is odd (or not :P ) works perfectly fine on IOS

enter image description here

tested on both debug and release versions of the Android app, on different devices, different Android SDK level


Solution

  • It has been fixed in 1.6.11


    This is a bug of Font composable. Reported it here.

    Until it's fixed you can reset it's value manually using key. Use FontHotfix instead of Font for now:

    @SuppressLint("ComposableNaming")
    @Composable
    // TODO: replace with system `Font` when https://github.com/JetBrains/compose-multiplatform/issues/4863 is fixed
    fun FontHotfix(
        resource: FontResource,
        weight: FontWeight = FontWeight.Normal,
        style: FontStyle = FontStyle.Normal,
    ) = key(resource) {
        Font(resource = resource, weight = weight, style = style)
    }