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"
/>
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);
}
}