airbnb / lottie-android

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

Dynamic Bitmap Images Rendering Issue #2545

Open edwin-pixel-1 opened 2 months ago

edwin-pixel-1 commented 2 months ago

Lottie is supported and developed on nights and weekends. Issues from Lottie sponsors will be prioritized.

Checklist

  1. My animation doesn't use any unsupported features. ✅
  2. I know what part of my animation doesn't work. ✅
  3. I have created a simplified version of my animation ❌
  4. I have attached the AEP file (as a zip file so it can be attached) that only has the part of the animation that doesn't work. ❌

Describe the bug I have used this library to load json animation file from API, along with multiple images loaded as Bitmap. I have this implementation working perfectly fine using the classic way using XML layout with LottieAnimationView reference... Here an example of this functional working code:

animationView.setAnimationFromJson(animationHolder.jsonAnimation, null)

// serverImages structure: Map<String, Bitmap>?
animationHolder.serverImages?.also { serverImages ->
    animationView.setImageAssetDelegate { lottieAsset ->
        serverImages[lottieAsset.fileName]
    }
}
animationView.playAnimation()

The problem comes now when I tried to do the same but with Lottie Compose... I added each bitmap image as dynamicProperty, but it doesn't work properly. Here it's a code example of it:

val animationHolder by myViewModel.animationHolder.collectAsState()

val composition by rememberLottieComposition(spec = LottieCompositionSpec.JsonString(animationHolder?.jsonAnimation ?: ""), cacheKey = null)

// serverImages structure: Map<String, Bitmap>?
val dynamicPropertyList = animationHolder?.serverImages?.let { serverImages ->
    val propertyList = mutableListOf<LottieDynamicProperty<Bitmap>>()
    serverImages.keys.forEach { key ->
        serverImages[key]?.also { bitmap ->
            val property: LottieDynamicProperty<Bitmap> = rememberLottieDynamicProperty(
                property = LottieProperty.IMAGE,
                keyPath = arrayOf(key),
                value = bitmap,
            )
            propertyList.add(property)
        }
    }
    propertyList.toTypedArray()
} ?: arrayOf()

if (dynamicPropertyList.isNotEmpty()) {
    val dynamicProperties = rememberLottieDynamicProperties(*dynamicPropertyList)

    val progress by animateLottieCompositionAsState(
        composition = composition,
        iterations = LottieConstants.IterateForever,
        clipSpec = clipping,
        isPlaying = true,
        restartOnPlay = true,
        speed = 3F, //TODO: Remove,
    )

    LottieAnimation(
        composition = composition,
        progress = { progress },
        modifier = Modifier
            .padding(vertical = 30.dp)
            .wrapContentHeight()
            .height(230.dp),
        dynamicProperties = dynamicProperties,
    )
}

Even doing all what is supposed to be done, the animation never renders well, doesn't show all the sequence correctly. So, after a lot of debugging and comparing it with the legacy way (xml layout), and trying a lot of workarounds, finally I found a way to solve it... Internally in the Library, in the file LottieAnimation, for the composable method LottieAnimation when it's setting up the drawable, I think it lacks calling drawable.setImageAssetDelegate {...} assigning the right images to the sequence. Would be great to fix this for future usages.

What version of Lottie did you test this on? 6.5.0

What version of Android did you test this on? Android 14, Android 13, Android 12

Steps To Reproduce

Screenshots

gpeal commented 1 month ago

Could you attach a sample project that reproduces this?