20190405のAndroidに関する記事は3件です。

[Android] もっと!Lottie

Lottie( http://airbnb.io/lottie/ )はAirbnb社が開発・公開しているアニメーションライブラリです。
アニメーションのjsonさえあれば、ImageViewと似た指定で簡単に扱えます。サンプルアプリ を入れてみると挙動がわかりやすいです。
jsonの作り方は他のドキュメントに任せて、Androidの実装側で色々やってみた例を紹介します。

きほん

アプリ内のassetsなどに置いたjsonを読み込む

 <com.airbnb.lottie.LottieAnimationView
         android:id="@+id/lottie_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:lottie_fileName="hello_world.json"
         app:lottie_loop="true"
         app:lottie_autoPlay="true" />

アプリ内に置かず、URLで指定する

 <com.airbnb.lottie.LottieAnimationView
         android:id="@+id/lottie_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         app:lottie_url="https://xxxxx/hello_world.json" />

もっと!

可変なURLを指定する

サーバからjsonのURLを取得して、その内容を表示させたいとき。これはxmlだけでは出来なくて、コードを書くことになります。

lottieView.setAnimationFromUrl(url)

この指定で表示はされます。しかし、URLが存在しなかったりロード出来なかったときに IllegalStateException が投げられてしまいます。
たぶんこの部分 https://github.com/airbnb/lottie-android/blob/master/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java#L66

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

落ちないように次のようにしました。

LottieCompositionFactory.fromUrl(this, url)
        .addFailureListener {
            // 読み込み失敗時の処理
        }
        .addListener {
            lottieView.setComposition(it)
        }

コードで動的に指定するときは lottieView.playAnimation() を忘れるとアニメーションが開始しないので注意です。

アニメーションが終わったら消す

AnimatorListenerかAnimatorListenerAdapterのListenerをセットし、アニメーションの開始や終了時の処理を記述できます。

lottieView.addAnimatorListener(object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animation: Animator?) {
        lottieView.visibility = View.GONE
    }
})

複数のアニメーションを連続して表示する

サーバから1つずつ表示したいアニメーションのURLを取得し、それをQueueに詰めてみることにしました。

private val lottieQueue: LinkedList<String> = LinkedList()
private val animationListener = object : AnimatorListenerAdapter() {
    override fun onAnimationEnd(animator: Animator) {
        playNextLottie()
    }
}
// 〜〜〜
{ // どこかでサーバから1つずつ取得する
    lottieQueue.add(enqueueURL) // 複数詰める
    playNextLottie()
}
// 〜〜〜
private fun playNextLottie() {
    val lottieUrl = lottieQueue.pollFirst()
    if (lottieUrl.isNullOrEmpty()) { // Queueから全てなくなったら終了
        disableLottieView() // listener解除など終了処理
        return
    }
    buildAndPlayLottieView(lottieUrl)
}

private fun buildAndPlayLottieView(url: String) {
    LottieCompositionFactory.fromUrl(context, url)
             .addFailureListener {
                 playNextLottie() // リンク切れなどのときは何もせず次へ
             }
             .addListener {
                 lottieView.setComposition(it)
                 lottieView.addAnimatorListener(animationListener)
                 lottieView.playAnimation()
             }
}

その後、これらの処理はcom.airbnb.lottie.LottieAnimationView を継承したCustomViewをつくって突っ込みました。

動的に取得したLottieを画面の横幅目一杯に表示する

match_parent して伸びるのはアニメーションの背景だけだったので、scaleを設定してみました。

LottieCompositionFactory.fromUrl(this, url)
        .addListener { lotteCompotition ->
           lottieView.scale = lottieView.measuredWidth.toFloat() / lotteCompotition.bounds.width()
        }

アスペクト比が固定なのであれば、 app:layout_constraintDimensionRatio で縦横比を指定して match_constraint でもいけてました。
scaleTypeも使えますが、 centerCropcenterInside しか使えないので注意です。

こまった!

おちた!

json内でフォントの指定がされており、そのフォントが見つからなかったときに落ちました。次のエラーが出ました。

Font asset not found fonts/BlackHanSans.ttf

特に文字は使っていなかったので、フォント指定のないjsonを作り直してもらいました。

でない!

ViewよりLottieが大きいと表示されませんでした。scaleで調整したりしました。

おもい!

古い端末だともっさりすることがあります。json側の作り方の方は詳しくないので、軽く作る良い方法があったら知りたいです。

おわりに

アニメーションはうまく使うとわかりやすいし楽しいです。参考になる記事などをいくつか載せておきます。良いLottieライフを!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PagerViewで左右どちらにフリックしたか判定する方法

    /** Touch前の座標*/
    private boolean mIsPagerViewTouchDown = false;

    pager.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            float touchX = event.getX();

            switch(event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mPreviousTouchPointX = touchX;
                    break;
                case MotionEvent.ACTION_UP:
                    float dx = touchX - mPreviousTouchPointX;

                    // TouchDown時のタッチ座標とTouchUp時の座標を比較しどちらにフリックしたか判定
                    if ((Math.abs(dx) > 1)) {
                        if (dx > 0) {
                            Log.d(MainActivity.class.getSimpleName(), "右へフリック"+dx);
                        } else {
                            Log.d(MainActivity.class.getSimpleName(), "左へフリック"+dx);
                        }
                    }
                    break;
                default:
                    break;
            }

            mPreviousTouchPointX = touchX;
            return false;
        }
    });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Androidのライブラリプロジェクト内のKotlinクラスを参照するとUnresolved referenceが出る問題対処

Androidプロジェクトから別のAndoridライブラリプロジェクト内のKotlinクラスを参照した時に、Unresolved referenceとなりビルドエラー発生。1hくらいはまったのでメモを残す。

原因

ライブラリプロジェクトのbuild.gradleにKotlin用の記述が漏れているため。
(Androidライブラリプロジェクト作成時、Kotolin用の記述は自動生成されない)

解決方法

ライブラリプロジェクトを開いて、以下を実施。
Tools -> Kotlin -> 'Configure Kotlin in projects'
(All modules with Kotlin files are configured'を選択してOK。

参考

https://stackoverflow.com/questions/49124353/unresolved-reference-errors-for-android-library-module-referenced-in-app-modul

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む