Search code examples
androidimageanimationdrawablelottie

Images not showing after load my lottie's json into LottieDrawable in SurfaceHolder


I have a Lottie json file, I play it with ValueAnimator after loaded in SurfaceView's LottieDrawable. But images are not showing, the animation is running without images!

But when I tested this json in LottieAnimationView, It just works fine. So what should I do to play in LottieDrawable? thx

LottieDrawable, play without images showing:

        if (lottieDrawable.composition == null) {
            //val url = "https://assets4.lottiefiles.com/packages/lf20_dkzdaf1z.json"
            //val task = LottieCompositionFactory.fromUrl(applicationContext, url)

            val input = applicationContext.assets.open("wallpaper_lottie.json")
            val task = LottieCompositionFactory.fromJsonInputStream(input, null)

            //val input = applicationContext.assets.open("wallpaper_lottie.zip")
            //val zip = ZipInputStream(input)
            //val task = LottieCompositionFactory.fromZipStream(zip, null)

            task.addFailureListener {
                Log.i(TAG, "LOT::addFailureListener, " + it.message)
            }
                task.addListener { comp ->

                    // lottie drawable
                    lottieDrawable.composition = comp
                    Log.i(TAG, "LOT::lottieDrawable.composition, 1 = ${lottieDrawable.composition.toString().subSequence(0, 15)}")

                    val lotDrawableWidth = (screenWidth * 90F / 100F).toInt()
                    val lotDrawableHeight = (screenWidth * 80F / 100F).toInt()
                    val statusBarHeight = 65
                    val lotDrawableLeft = ((screenWidth - lotDrawableWidth) / 2).toInt()
                    val lotDrawableTop = (screenHeight - statusBarHeight).toInt()
                    lottieDrawable.bounds = Rect(
                        lotDrawableLeft,
                        lotDrawableTop,
                        lotDrawableLeft + lotDrawableWidth,
                        lotDrawableTop + lotDrawableHeight,
                    )

                    // lottie animator
                    lottieAnimator.cancel()
                    lottieAnimator.setIntValues(0, lottieDrawable.maxFrame.toInt())
                    lottieAnimator.repeatCount = LottieDrawable.INFINITE
                    lottieAnimator.duration = 6000
                    lottieAnimator.addUpdateListener { anim ->
                        val frame = anim.animatedValue as Int
                        lottieDrawable.frame = frame
                        // lottieDrawable.draw(canvas)
                        Log.i(TAG, "LOT::addUpdateListener, frame = ${lottieDrawable.frame}")
                    }
                    lottieAnimator.start()
                }
            }

LottieAnimationView, play with image showed:

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/iv_scanning"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        app:lottie_fileName="wallpaper_lottie.json"
        app:lottie_loop="true"
        />

Solution

  • Finally I play it using ValueAnimator, and FakeAnimView did the trick. Wish to help:

        fun draw() {
            val screenWidth = canvas.width.toFloat()
            val screenHeight = canvas.height.toFloat()
    
            // draw lottie drawable
            // https://github.com/airbnb/lottie-android/issues/1177
            if (lottieDrawable.composition == null) {
    
                val input = applicationContext.assets.open("anim/lottie.json")
                val task = LottieCompositionFactory.fromJsonInputStream(input, null)
    
                task.addFailureListener {
                    if (BuildConfig.DEBUG) {
                        Log.i(TAG, "LOT::drawPreview, addFailureListener, " + it.message)
                    }
                }
                task.addListener { comp ->
    
                    // lottie drawable
                    lottieDrawable.composition = comp
    
                    val lotDrawableWidth = (screenWidth * 80F / 100F).toInt()
                    val lotDrawableHeight = (screenWidth * 60F / 100F).toInt()
                    val statusBarHeight = if (Sdk30PermissionUtil.hasSdk30()) 0F else 65F
                    val lotDrawableLeft = ((screenWidth - lotDrawableWidth) / 2).toInt()
                    val lotDrawableTop = (screenHeight - statusBarHeight).toInt()
                    lottieDrawable.bounds = Rect(
                        lotDrawableLeft,
                        lotDrawableTop,
                        lotDrawableLeft + lotDrawableWidth,
                        lotDrawableTop + lotDrawableHeight,
                    )
    
                    // lottie animator
                    lottieAnimator.cancel()
                    lottieAnimator.setIntValues(0, lottieDrawable.maxFrame.toInt())
                    lottieAnimator.repeatCount = LottieDrawable.INFINITE
                    lottieAnimator.duration = 6000
                    lottieAnimator.addUpdateListener { anim ->
                        val frame = anim.animatedValue as Int
                        lottieDrawable.frame = frame
                        if (BuildConfig.DEBUG) {
                            Log.i(TAG, "LOT::lottieAnimator.addUpdateListener, frame = ${lottieDrawable.frame}")
                        }
                    }
                    lottieAnimator.start()
    
                    ReleaseUtil.release(input) //! prevent OOM
                }
            }
    
            if (lottieDrawable.composition != null) {
                if (BuildConfig.DEBUG) {
                    Log.i(TAG, "drawPreview, setDelegate")
                }
                WallpaperUtil.setDelegate(applicationContext, lottieDrawable)
                // draw lottie drawable
                val lotDrawableWidth = (screenWidth * 80F / 100F).toInt()
                val lotDrawableHeight = lotDrawableWidth
                val transX = (screenWidth - lotDrawableWidth) / 2
                val transY = 365F
                canvas.translate(transX, transY)
                lottieDrawable.draw(canvas)
    
            }
        }
    
    
    
        fun setDelegate(context: Context, lottieDrawable: LottieDrawable) {
            try {
                if (BuildConfig.DEBUG) {
                    Log.i(TAG, "setDelegate")
                    Log.i(TAG, "setDelegate, lottieDrawable.getCallback = " + lottieDrawable.callback)
                }
    
                if (lottieDrawable.callback == null) {
                    lottieDrawable.callback = FakeAnimView(context, null)
                }
                lottieDrawable.setImageAssetDelegate { asset: LottieImageAsset ->
                    var bitmap: Bitmap? = null
    
                    try {
                        val filePath = "anim/images/"
                        val fileName = asset.fileName
                        bitmap = getBitmapFromAsset(context, filePath + fileName)
    
                        if (BuildConfig.DEBUG) {
                            Log.i(TAG, "setDelegate, fileName=$fileName")
                            Log.i(TAG, "setDelegate, bitmap=$bitmap")
                        }
    
                    } catch (t: Throwable) {
                        t.printStackTrace()
                        Log.i(TAG, "setDelegate, Throwable = $t")
                    }
    
                    bitmap
                }
            } catch (t: Throwable) {
                t.printStackTrace()
                Log.i(TAG, "setDelegate, Throwable = $t")
            }
        }
    
    
    
    
    /* loaded from: classes2.dex */
    public class FakeAnimView extends View {
        public FakeAnimView(Context context, @Nullable AttributeSet attributeSet) {
            super(context, null);
        }
    
        @Override // android.view.View
        public int getVisibility() {
            return VISIBLE;
        }
    
        @Override // android.view.View
        protected void onMeasure(int i2, int i3) {
            super.onMeasure(200, 200);
        }
    }