1. ホーム
  2. アンドロイド

Lottieの使用方法とソースコードの詳細

2022-02-22 06:47:18
<パス

I. 前述したこと

Androidの開発では、各モジュールの構築やメンテナンスはもちろん、アニメーションの作成もCoderが担当することになります。より使いやすいインターフェイスにするために、デザインライオンがある程度デザインした後、デベロッパーに渡してアプリに再現してもらうのが一般的です。アニメーションのアプリを見るのは初めてです。

Android 5.0の時点で、Googleはすでにベクターベクター画像のサポートを提供しており、それらは"move"することができます。

この問題を解決することで、新たな落とし穴が生まれました。仮にまとめると、次のようになります。

  • Android 4.xでは、ベクターの経路変換アニメーションを解決することはできません。
  • Android 4.xでは、システムに付属しているインターポレーターしか使用できず、カスタマイズはできない
  • 動的なベクターアニメーションを作成するのは簡単ではありません。静的なベクターパスを作ってから動的なベクターパスの変更値を実装するのは面倒な作業です。

その結果、Lottieが登場するまでは、主要なアプリのほとんどにダイナミックベクターが登場する気配がありませんでしたが、Lottieの登場により、ダイナミックベクターが登場するようになりました。

II. LOTTIEの紹介

1、エフェクトショー(心をつかむには、目をつかまなければならない)



2. ロティとは?

  • LottieはAirbnbのオープンソースアニメーションレンダリングライブラリで、Android、IOS、React Native、Webの両方のプラットフォームに対応しています。Lottieを使用することで、アニメーションを簡単かつ便利に表示することができます。

  • アニメーション作成からアニメーション表示までの流れは以下の通りです。

  • ワークフローです。

  • 注意

    各プラットフォーム(Android、IOS、React Netive)用のアニメーションを作成するデザイナー学生は、異なるプラットフォームでLottieがサポートする機能を確認する必要があり、そうしないと、作成したアニメーションが表示に問題がある場合があります、アニメーションを作るデザイン学生は、以下を参考にしてください。 Lottieの各プラットフォームへの対応機能

3. なぜLOTTIEを使うのか?

  • まず、Lottie以前の複雑なアニメーションの実装方法について見てみましょう。

    • GIFを使うと、容量を食う、アニメーションによっては表示が悪い、解像度に合わせる必要がある、AndroidはGIFアニメーションの表示をネイティブでサポートしていない、などの問題があります。
    • フレームアニメーションを使用する。多くのスペースを占め、なおかつ異なる解像度に適応する問題が発生する。
    • 複雑なアニメーション効果を実現するために多くのコードを使用する、コンビナトリアルアニメーション。
  • ロッテで解決できる問題。

    • アニメーションを書かずに、読み込むだけで開発できる
    • Android、iOS、React Nativeのマルチプラットフォーム対応
    • 手動での進捗設定、ジェスチャー、イベント等のバインド
    • ネットワークローディング、再生速度の動的制御など。
    • アニメーションの設計・開発コストを削減
    • デザインから提供されたアニメーションと実装の不一致を解消
    • フットプリントの縮小
    • 異なる携帯電話の解像度に対応する必要がない

4. LOTTIEはどのようなシナリオに適用されるのですか?

  • 起動(スプラッシュ)アニメーション:典型的なシナリオは、アプリのロゴアニメーションを再生することです。
  • リフレッシュアニメーション:すべてのアプリに必要なものですが、Lottieはそれをよりシンプルに、よりクールにすることができます。
  • ロードアニメーション:典型的なシナリオは、Webリクエストのロードアニメーションです。
  • ヒントアニメーション:典型的なシナリオは、白紙ページのヒントです。
  • ボタンアニメーション:代表的なシナリオは、スイッチボタン、エディットボタン、プレイボタンなど
  • ギフト(贈り物)アニメーション:代表的なシナリオは、ライブアプリの高度なアニメーション再生

5. LOTTIEの代わりにどのアニメーションを使いたいですか?

  • まず、アプリ内のすべてのアニメーションをLottieに置き換える必要はありません。
  • プロパティアニメーションで実現できる簡単なアニメーションは、Lottieである必要がないものもあります
  • コードでうまく実装できない一部のアニメーションを置き換えます。
  • GIFアニメーション、フレームアニメーションの差し替え

三、LottieAndroidの利用について

1. プロジェクトに組み込む(バージョン2.2.0を例とする)

  • 依存関係の追加: 'com.airbnb.android:lottie:2.2.0' をコンパイルします。

    Lottieのバージョン番号の参照。 Lottieのバージョン番号を表示するためのMavenリポジトリ

  • Gradleの依存関係の修正。

    最小バージョンです。min_sdk_version = 16

    コンパイルバージョン。コンパイルバージョン = 25

    すべての互換性パッケージをバージョン 25.3.1 にアップグレードする必要があります。

compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:recyclerview-v7:25.3.1'
compile 'com.android.support:palette-v7:25.3.1'
compile 'com.android.support:support-v4:25.3.1'


  • Lottieの各バージョンが対応する必要があるAndroidSDKのコンパイルバージョンと互換性パッケージのバージョン番号はどのように表示されますか?

    Lottieバージョン2.2.0を例にとると。 mvnrepository ロットー2.2.0

2. 使用方法

  • Lottieの基本的な使用方法ビュー 公式ドキュメント

    • まず、jsonファイルをassetsフォルダの

      assetsディレクトリに直接入れるか、assetsディレクトリにセカンダリディレクトリを作って入れてください。

  • LottieAnimationView コントロールをレイアウトに追加します。

    上記と同様に、assetsサブフォルダにjsonファイルがある場合は、lottie_fileName="lottieani/stars.json"とします( また、ZIP形式で圧縮することも可能です )

      <com.airbnb.lottie.LottieAnimationView
          android:id="@+id/animationView"
          android:layout_width="match_parent"
          android:layout_height="0dp"
          android:layout_weight="1"
          airbnb:lottie_fileName="lottieani/stars.json"
          airbnb:lottie_autoPlay="true"
          airbnb:lottie_loop="true"/>
    
    
    

    LottieAnimationViewに設定可能なプロパティは以下の通りです。

     <declare-styleable name="LottieAnimationView"> //remember that you can't just change this name, it's the official naming
       <attr name="lottie_fileName" format="string" /> //It is worth mentioning that: lottie_fileName and lottie_rawRes cannot be set at the same time, otherwise it will report an error.
       <attr name="lottie_rawRes" format="reference" />
       <attr name="lottie_url" format="string" />
       <attr name="lottie_autoPlay" format="boolean" />
       <attr name="lottie_loop" format="boolean" />
       <attr name="lottie_repeatMode" format="enum">
             <enum name="restart" value="1" />
             <enum name="reverse" value="2" />
         </attr>
       <attr name="lottie_repeatCount" format="integer" />
       <attr name="lottie_imageAssetsFolder" format="string" />
       <attr name="lottie_progress" format="float" />
       <attr name="lottie_enableMergePathsForKitKatAndAbove" format="boolean" />
       <attr name="lottie_colorFilter" format="color" />
       <attr name="lottie_scale" format="float" />
     </declare-styleable>
    
    
    
    
    • アニメーション用のLottieAnimationViewオブジェクトを取得します。
    LottieAnimationView animationView = (LottieAnimationView)findViewById(R.id.animation_view);
    // The layout does not specify a file to be set here, the path is set to the same as the layout file
    animationView.setAnimation("hello-world.json");
    // Whether to loop or not
    animationView.loop(true);
    // Set the speed, e.g. 2 means the speed is twice as fast as when it is not set.
    animationView.setSpeed(2f);
    // start playing
    animationView.playAnimation();
    
     // pause the playback
    animationView.pauseAnimation();
    // cancel the playback
    animationVIew.cancelAnimation();
    
    // Set the progress of the playback
    animationView.setProgress(0.5f);
    // Determine if it is playing or not
    animationView.isAnimating();
    
    
    
    

    setAnimation()には、アニメーションのJsonオブジェクトを直接設定する方法と、Jsonファイルの相対パス名を設定する方法の6つがあります。

    setAnimation(@RawRes final int rawRes)
    setAnimation(final String assetName) 
    setAnimationFromJson(String jsonString) //not recommended
    setAnimationFromJson(String jsonString, @Nullable String cacheKey)
    setAnimation(JsonReader reader, @Nullable String cacheKey)
    setAnimationFromUrl(String url)
    
    
    

    playAnimation()には、1つのメソッドがあります。

     public void playAnimation() 
    
    
    

    キャッシュの種類を指定する CacheStrategy プロパティを見たことがあるかもしれませんが、これは上位バージョン (V2.7.0) で削除され、公式には次のように説明されています。

    <ブロッククオート これは、LottieCompositionFactoryに関連する様々なことをクリーンアップするものです。
    それ
    LottieCompositionFactory レベルでのタスクキャッシングを処理し、コンポジションがキャッシュされない場所でも動作することを保証しました。
    LottieAnimationViewのタスク処理方法を簡略化しました。
    修正 #958 RawRes アニメーションで異なるキャッシュキーが使用される場合
    非推奨のファクトリーAPIを削除

    • アニメーションリスナーを追加する
    animationView.addAnimatorListener(new Animator.AnimatorListener() {
     @Override
     public void onAnimationStart(Animator animation) {
         Log.d(TAG, "onAnimationStart : " + animation.getDuration());
     }
    
     @Override
     public void onAnimationEnd(Animator animation) {
         Log.d(TAG, "onAnimationEnd");
     }
    
     @Override
     public void onAnimationCancel(Animator animation) {
         Log.d(TAG, "onAnimationCancel");
     }
    
     @Override
     public void onAnimationRepeat(Animator animation) {
         Log.d(TAG, "onAnimationRepeat");
     }});
     
     mAnimationView.addAnimatorUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
     @Override
     public void onAnimationUpdate(ValueAnimator animation) {
         //Log.d(TAG, "onAnimationUpdate : " + animation.getCurrentPlayTime());
     }
     });
    
    
    

IV. ソースコード解析

1. Jsonからアニメーション表示までの実装の考え方

  • Design Lionは、複雑な画像を複数のレイヤーで表現し、各レイヤーはコンテンツの一部を表示し、レイヤー内のコンテンツは複数の要素に分割することが可能です。要素を分割した後、アニメーションの要求に応じて、レイヤーまたはレイヤー内の要素を個別にパン、回転、縮小などのアニメーションを行うことができます(主にキャンバス描画とマトリックスの操作による)。

  • JsonファイルのデータはLottieCompositionデータオブジェクトに変換され、LottieDrawableはデータをdrawableに描画する役割を担い、LottieAnimationViewはLottieDrawableを表示する役割を担っているのだそうです。LottieAnimationViewはAppCompatImageViewを、LottieDrawableはDrawableを継承しています。

2. まず生成されたJsonデータを見てみましょう

<ブロッククオート

Lottieは、まずAdobe After Effects(AE)が生成するaepアニメーションのプロジェクトファイルを、bodymovin(bodymovinプラグイン自体は、AEの各種効果をWeb上でレンダリングするためのオープンソースライブラリ)を介して共通のjson形式の記述ファイルに変換しなければならないリソースを使っています。 それぞれのアニメーションがある時点の状態を計算して画面に正確に描画しているのです。

このJSONはLottieのユニットテストから引用されています。

{
    "v": "4.11.1", //using bodymovin's version
    "fr": 60, //frame rate
    "ip": 0, //start keyframe
    "op": 180, //end keyframe
    "w": 300, //width of the view
    "h": 300, //height of the view
    "nm": "Comp 1", //not parsed from the source code
    "ddd": 0,      
    "assets": [], //image collections
    "layers": [ //collection of layers
        {
            "ddd": 0,
            "ind": 1, //layer's Id, unique
            "typ": 4, //the type of the layer, numeric
            "nm": "Shape Layer 1", //the name of the layer, unique in ae generation
            "sr": 1,
            "ks": {}, //appearance information
            "ao": 0,
            "shapes": [], //array of vector graphics layers
            "ip": 0, // the starting keyframe of the layer
            "op": 180, // the end keyframe of the layer
            "st": 0,       
            "bm": 0
        },
        {...} ,
        {...} ,
        {...} ,
    ]
}



以下は、フィールドの詳細な説明です。 bodymovin Json解析

3. JSONデータを読み込んで画像を表示するには?

animationView.setAnimation("hello-world.json") を実行します。

setAnimation()を通して、上記のjsonデータがどのように表示画像に反映されるかを見てみましょう。ソースコードのタイミング図は以下の通りです。

  • 1、LottieAnimationViewの初期化は、まずLottieDrawableオブジェクトを作成し、初期化のためのinit()関数、プロパティのxml設定をパースすることになります。

LottieDrawableオブジェクトを作成するコードスニペットです。

@SuppressWarnings({"unused", "WeakerAccess"}) 
public class LottieAnimationView extends AppCompatImageView {

  private static final String TAG = LottieAnimationView.class.getSimpleName();

  private final LottieListener
 loadedListener = new LottieListener
() {
    @Override public void onResult(LottieComposition composition) {
      setComposition(composition);
    }
  };

  private final LottieListener
 failureListener = new LottieListener
() {
    @Override public void onResult(Throwable throwable) {
      throw new IllegalStateException("Unable to parse composition", throwable);
    }
  };

  private final LottieDrawable lottieDrawable = new LottieDrawable();
...


init()関数のコードスニペットです。

private void init(@Nullable AttributeSet attrs) {
    TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.LottieAnimationView);
    if (!isInEditMode()) {
      boolean hasRawRes = ta.hasValue(R.styleable.LottieAnimationView_lottie_rawRes);
      boolean hasFileName = ta.hasValue(R.styleable.LottieAnimationView_lottie_fileName);
      boolean hasUrl = ta.hasValue(R.styleable.LottieAnimationView_lottie_url);
      if (hasRawRes && hasFileName) {
        throw new IllegalArgumentException("lottie_rawRes and lottie_fileName cannot be used at " +
            Please use only one at once.");
      } else if (hasRawRes) {
        int rawResId = ta.getResourceId(R.styleable.LottieAnimationView_lottie_rawRes, 0);
        if (rawResId ! = 0) {
          setAnimation(rawResId);
        }
      } else if (hasFileName) {
        String fileName = ta.getString(R.styleable.LottieAnimationView_lottie_fileName);
        if (fileName ! = null) { setAnimation(fileName)
          setAnimation(fileName);
        }
      } else if (hasUrl) {
        String url = ta.getString(R.styleable.LottieAnimationView_lottie_url);
        if (url ! = null) {
          setAnimationFromUrl(url);
        }
      }
    }
   ....
  }


  • 2, setAnimation(String assetName), JSONファイルを読み込む。主にLottieCompositionFactoryとLottieComposition.Factoryクラスで読み込まれますが、そのうちLottieComposition.Factoryは公式に非推奨とされています。

setAnimation()関数のコード。

 public void setAnimation(final String assetName) {
    this.animationName = assetName;
    animationResId = 0;
    setCompositionTask(LottieCompositionFactory.fromAsset(getContext(), assetName)); //it loads the resource asynchronously, and after successful loading, there will be a callback accordingly
  }


setCompositionTask関数のコードスニペットです。

 private void setCompositionTask(LottieTask
 compositionTask) {
    clearComposition();
    cancelLoaderTask();
    this.compositionTask = compositionTask
            .addListener(loadedListener)
            .addFailureListener(failureListener);
  }


ガイドを呼び出す。

  • 3. 非同期に読み込むことで、最終的にfromJsonSync()を呼び出してJsonファイルをパースします。
    LottieCompositionFactory.fromAsset()関数のコードです。
  public static LottieTask
 fromAsset(Context context, final String fileName) {
    // Prevent accidentally leaking an Activity.
    final Context appContext = context.getApplicationContext();
    return cache(fileName, new Callable<LottieResult
>() { //here it will first look for it in the cache, and only load the resource if it can't find it
      @Override public LottieResult
 call() {
        return fromAssetSync(appContext, fileName);
      }
    });
  }

private void notifyListeners() { // Listeners should be called on the main thread. handler.post(new Runnable() { @Override public void run() { if (result == null || task.isCancelled()) { return; } // Local reference in case it gets set on a background thread. LottieResult result = LottieTask.this.result; if (result.getValue() ! = null) { notifySuccessListeners(result.getValue()); } else { notifyFailureListeners(result.getException()); } } }); }