📜 ⬆️ ⬇️

The practice of using the lottie library in the bank’s mobile application

Hi, Habr!

At one time, the Product Owner asked us to think about creating an effective process for introducing animation into our application on android / ios. At that time we did the task of pre-filling the application with personal data for the loan product, and the response from the server took some time, during which we wanted to show a beautiful loading animation.


The task was clear: the designer wanted to draw beautifully, to give the source code to both at once.
platforms without dopilivany on his part, and so that all this does not lag on old devices (yes, we still support android 4.1).
')
What were my options for introducing animation:

  1. Handles using animated vector drawable. The pros are that the rendering works.
    in a separate thread (starting with api 25), the downsides are the difficulty of creating such animations and a small number of manipulations with objects. For simple animations, this all works well, but a little harder, and hell begins. Yes, and on different platforms you will not get.
  2. Gif - weigh a lot, have a fixed size, and therefore do not scale normally. And you will not make any manipulations with them.
  3. Sequence png (no comments).

Having rummaged some time towards the native vector animation of android and gif (oh god, we still considered this option), I remembered the wonderful library Lottie, and showed it to my colleagues.

After some tests with different devices, we decided that the library should be implemented, especially since its capabilities were impressive. The designer was especially pleased, now he could do almost any animation in Adobe After Effects, and export it to a json file with a few clicks. We were delighted, but first things first.

Lottie was designed and implemented by Airbnb in response to a growing demand for cross-platform animation, so it works the same (well, almost) on all platforms. The developers themselves claim that their goal is to realize the maximum number of After Effects features, and they succeeded in that. Now implementing a Lottie animation is as easy as inserting a picture into an ImageView.

Key 3 classes:

  1. LottieAnimationView is an inheritor of ImageView, and the easiest way to use animation. You can describe the animation in xml, or in the code, most methods are supported.
  2. LottieDrawable - the heir to Drawable, with the same functionality as the previous class, allows you to apply animation to any view.
  3. LottieComposition and its companion LottieCompositionFactory allow you to preload animations from various sources and apply them to LottieDrawable and LottieAnimationView.

Resource download


Supports resource loading from:

  1. res / raw
  2. src / assets
  3. Json strings
  4. Any url from the network leading to a json or zip file (implemented through HttpURLConnection, in order not to add external dependencies. If you have animation with images, then you need to use zip)
  5. InputStream json or zip file

Caching animation


The cool thing is that all the animations loaded via res / raw or assets are saved with LRU cache, which allows you not to waste user time again on loading and parsing the animation, as in the case of complex animation it may take some time. What's even cooler if you need to preload the animation, and then in the next snippet to display the animation instantly, you can use the code

LottieCompositionFactory.fromRawRes(context, rawFile) 

The animation is cached using the rawFile key, and where you really need to use it, it will start almost instantly.

Progress management


Lottie allows you to set the current animation state via setProgress (...). This can be useful if you want to animate the file download status, scroll position, various gestures, etc. I saw various implementations on BottomSheets, PullToRefresh, CollapsingToolbarLayout.

Here's how to use progress with AppBarLayout:

 appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset -> val percent = Math.abs(verticalOffset).toFloat()/appBarLayout.totalScrollRange animationView.progress = percent }) 

Looping


Lottie supports looping playback of setRepeatMode () or setRepeatCount () not only the whole animation, but also any fragment within (0.0 ... 1.0). This is implemented by the properties setMinFrame, setMaxFrame, setMinAndMaxFrame. We used this to not implement 3 animations for different file loading states: idle, progress, complete. Here is a small piece of code that solves this:

 when (loadingStatus) { LoadingStatus.IDLE -> { animationView.setMaxProgress(0.1f) } LoadingStatus.PROGRESS -> { animationView.setMinAndMaxProgress(0.2f, 0.9f) animationView.repeatCount = LottieDrawable.INFINITE animationView.playAnimation() } LoadingStatus.COMPLETE -> { animationView.setMinAndMaxProgress(0.9f, 1f) animationView.repeatCount = 1 animationView.playAnimation() }} 


Pictures


One of the main advantages of Lottie for us is that the library supports the insertion of images directly into the animation. Moreover, you can insert both a static image and a dynamic image downloaded from the Internet. Now I will explain how it works.

In the case of a static picture, everything is simple: the designer uploads to you an archive containing json plus the picture itself.

 { "v": "5.1.13", "fr": 29.9700012207031, "ip": 0, "op": 47.0000019143492, "w": 1034, "h": 1334, "nm": " 1", "ddd": 0, "assets": [ { "id": "image_0", "w": 130, "h": 436, "u": "images/", "p": "img_0.png" }, { "id": "comp_0", "layers": [ ... ]}] } 

This img_0.png, this is the picture that you need to put in src / assets, and which will be inside the animation.

For dynamic loading, the setImageAssetDelegate method is used, to which you must transfer a bitmap. We preload the picture with Glide, so at the stage of opening the fragment with animation and the picture, everything comes from the cache, so everything is pretty fast. Here is the code:

 glideLoader.loadAsBitmap(imageUrl).into(object: CustomTarget<Bitmap>() { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { viewAnimation.setImageAssetDelegate(object: ImageAssetDelegate { override fun fetchBitmap(asset: LottieImageAsset?): Bitmap { asset?.let { val resizeBitmap =Bitmap.createScaledBitmap(resource, it.width, it.height, true); return resizeBitmap } ?: run { return resource } } }) setAnimation(viewAnimation, animationImage) } override fun onLoadCleared(placeholder: Drawable?) {} }) 


Performance


Of course, it is better not to use a lot of animation on screens where the user spends a lot of time, as it is demanding on the processor. According to our tests, the processor load on some animations reaches 20%. Therefore, the ideal case of such an animation is interactive elements that work once.

If the animation on some devices slows down, sometimes it helps

 viewAnimation.useHardwareAcceleration(true) 

However, developers recommend using this method with caution, since different phones use hardware acceleration differently, so instead of acceleration, you can get the opposite effect.

Conclusion


In general, using the Lottie library greatly simplifies the implementation of animation in the application.

The main advantages of lottie, which we have identified:

  1. Small library size (300 kb)
  2. Cross-platform solution ios / android / web
  3. Download animations from the network
  4. Progress management and looping on any site
  5. A large number of features from the after effects allows the designer to realize the intended effect.

Minuses:

  1. Rendering is performed in the main stream, and fps can drop significantly in an application.
  2. Parsing a lottie animation can take a significant amount of time with complex animations.


By the way, to check how resource-intensive animation, you can use the official Lottie application from Google Play . There is a Render Graph, where you can see the time for rendering a frame, and also see what the animation will look like if you cut it into frames, or how hardwareAcceleration will affect and much more.

Source: https://habr.com/ru/post/459852/


All Articles