airbnb / lottie-android

Render After Effects animations natively on Android and iOS, Web, and React Native
http://airbnb.io/lottie/
Apache License 2.0
34.92k stars 5.4k forks source link

Incorrect icon loading when manually selecting a dark or light theme #2482

Closed sainz closed 4 months ago

sainz commented 5 months ago

In a project, I'm using the latest Lottie library for Compose, version 6.4.0, and the latest version of Compose (1.6.3, and BOM 2024.02.02). In this application, users are given the option to set the theme, choosing between System, Dark, or Light. There are JSON files loaded in the raw and raw-night directories to have animations for both dark and light themes.

When the "System" setting is chosen, everything works correctly: setting the theme from the Android settings loads the resources correctly from the raw or raw-night folder. However, it doesn't work when manually selecting the theme, thus having a configuration different from the operating system. For example, if the system theme is set to dark, but the application has a light theme, the animations from the raw-night folder will be loaded.

Steps to reproduce the behavior:

  1. Have a differente files on raw and raw-night folder
  2. Force Compose to use the light theme. For example:

    @Composable
    fun WeatherTheme(
    darkTheme: Boolean = false //isSystemInDarkTheme(),
    dynamicColor: Boolean = true,   // Dynamic color is available on Android 12+
    content: @Composable () -> Unit
    ) {
    val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }
        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    
    val customColorScheme =
        if (darkTheme) DarkCustomColorScheme
        else LightCustomColorScheme
    
    val view = LocalView.current
    }
  3. In a simple Screen, I use this method to load the animation:
    
    val composition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.icon))

LottieAnimation( composition = composition, modifier = modifier .weight(1f) .size(164.dp), iterations = LottieConstants.IterateForever, )



4. Set the system theme to dark
5. The resource will be loaded from the "raw-night" folder instead of "raw".
gpeal commented 5 months ago

Dark/Light Compose themes are just different sets of colors in your codebase. Lottie doesn't have any way of knowing which theme you're using so you'll need to manually set whichever composition is important. Alternatively, if you can pass in a context that has its configuration ui mode set to night, then LocalContext will return a dark mode set of resources This is untested but something like this:

val contextWrapper = ContextThemeWrapper(applicationContext, R.style.YourDarkTheme)
val configuration = Configuration(contextWrapper.resources.configuration)
configuration.uiMode = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK.inv() or Configuration.UI_MODE_NIGHT_YES
val context = contextWrapper.createConfigurationContext(configuration)