フェードインやフェードアウト

点滅の前に一番よくあるアニメーションであるフェードインやフェードアウトについて言及しておく。 Android 2.x 系の時は Animation クラスを使用した古いやり方をしていたと思うが Android 4.x 以上では ObjectAnimator を使う:

// ビューの alpha 値を 1 から 0 に変化させるアニメーション
ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
    addListener(object : Animator.AnimatorListener {
        override fun onAnimationEnd(animation: Animator?) {
            view.visibility = View.GONE  // アニメーション終了時にビュー自体を非表示にする
        }
        override fun onAnimationCancel(animation: Animator?) = Unit
        override fun onAnimationStart(animation: Animator?) = Unit
        override fun onAnimationRepeat(animation: Animator?) = Unit
    })
    duration = 1000  // 1,000 ミリ秒で実行
    start()
}

この ObjectAnimator.ofFloat() を使うと任意の時間内に任意のプロパティを滑らかに変更させることができるので、ほとんどの場面はこれでいけるはずだ。 この例ではフェードアウトさせるアニメーションなのだが、フェードアウトさせた後にビュー自体の存在判定を消さないと当たり判定として残り続けてしまう (alpha = 0 では透明度が 0 になっているだけでタップした際のイベントは走ってしまう)。 その為アニメーション終了時に visibility に対し GONE をセットしている。 これ自体は Android 2.x 時代からの使い古された手法だ。

点滅

ビューを点滅 (blink) させるというのは marquee と共に古いホームページの技法のように思えるが、今回実装する機会があったのでメモ。 数百ミリ秒ごとに visibility を切り替えてもいいのだが、それだとチカチカとした感じの古いタイプの点滅になってしまう。 フェードイン・フェードアウトを繰り返すタイプの点滅にしたい。

ObjectAnimator に逆方向にリピートする為の設定があったので、これを使えば短いコード量で実現できた:

ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.0f).apply {
    repeatCount = ObjectAnimator.INFINITE  // 無限に繰り返す
    repeatMode = ObjectAnimator.REVERSE  // 逆方向に繰り返す
    duration = 500
    start()
}

repeatModeObjectAnimator.RESTART という定数も入れることができるが、こちらだとただ単に 1.0 から 0.0 へのアニメーションを繰り返すような動きになる。 ObjectAnimator.REVERSE にすると alpha に対し 1.0 から 0.0 へのアニメーションが終わった後 0.0 から 1.0 へ再度アニメーション、その後そのパターンが永遠に繰り返されることになる。