Androidマンになりたいおじさん

自分の備忘録的なのです。Androidを普及できたらいいなと思ったりしながら書きます

アニメーションで遊びたい

こんにちは、こんばんわ!!!!!!!

こちら、サークル用のネタ記事投稿です


皆さん、アニメーション使ってますか...?

僕も最近ぬるぬるしたアニメーションを使ってみたいなーと思ったりしてるわけです


僕はAndroidな人間なので、Androidのアニメーションを見ていこうと思います!!!!!


まず公式から、どんなAnimationがあるのか見よう
developer.android.com

Property Animation

  • API level 11 以降で使えるっぽい(つよい)
  • View 以外のオブジェクトにも適用できる(つよい)

後述するView AnimationはViewにしか適用できないのですが、こちらは任意のオブジェクトに対して、アニメーションできるっぽい(つよい)

今回はその中の1つの楽にアニメーションを提供してくれるObjectAnimatorを使ってみよう!!

動作が分かりやすいようにrepeatCountを-1に設定して繰り返させてます!


基本構文はこんな感じです

ObjectAnimator.ofFloat(targetObject, "propName", 1f)

でわ、動作を見ていきましょう!!

translationX

// X軸にふぃ〜って動かすよ
    private fun animateTranslation(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "translationX", 1000f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/61e1d2b2bd6ab0f7b6cd2690d5d082f7.gif

translationY

// Y軸ににふぃ〜って動かすよ
    private fun animateTranslationY(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "translationY", 1000f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/700deeef2ff0fc56668c9773f23b2e97.gif

同じImageViewに対して、上記2つを適用してあげたら斜め移動も可能ですね!


rotaion

//  Z軸周りに回転させるよ
    private fun animateRotation(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "rotation", 1000f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/ed1ec05d12599203e4b420c26ee3c7bc.gif




rotaionX

//  X軸周りに回転させるよ
    private fun animateRotationX(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "rotationX", 1000f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/a7dca8ab7c357ee906118fa451808a35.gif


rotaionY

//  Y軸周りに回転させるよ
    private fun animateRotationY(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "rotationY", 1000f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/e77afa02c89405cfc997df2e78311da1.gif


scaleX

//  X軸に拡大させるよ
    private fun animateRotationY(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "rotationY", 2f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/26d1e4a8c8ed0ad08e62c7c025c4f889.gif


scaleY

// Y方向に拡大
    private fun animateScaleY(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "scaleY", 2f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/d2834f58c48a9000efbb123180b46726.gif

alpha

// 透過させるよ
    private fun animateAlpha(img: ImageView) {
        val objectAnimator = ObjectAnimator.ofFloat(img, "alpha", 1f, 0f)
        objectAnimator.duration = 2000
        objectAnimator.repeatCount = -1
        objectAnimator.start()
    }

https://i.gyazo.com/af833a3c4e6eae79136b8de789ccf7b9.gif


AnimatorSet
複数のアニメーションを同時に動かしたいときにグルーピングして扱ってくれます
今回僕はデータバインディングを使っているので気をつけてください!

class MainActivity : AppCompatActivity() {

    lateinit var mBinding: ActivityMainBinding
    private var isReversed: Boolean? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mBinding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)

        mBinding.card.tag = false
        mBinding.card.setOnClickListener {
            reverseCard(mBinding.card, 1.0f, 0.0f, 1.0f, 1.0f)
            isReversed = true
        }
    }

    private fun reverseCard(img: ImageView, vararg rotate: Float) {
        val scaleX = ObjectAnimator.ofFloat(img, "scaleX", rotate[0], rotate[1])
        val scaleY = ObjectAnimator.ofFloat(img, "scaleY", rotate[2], rotate[3])
        val animatorSet = AnimatorSet()
        animatorSet.interpolator = LinearInterpolator()
        animatorSet.playTogether(scaleX, scaleY)
        animatorSet.duration = 300
        animatorSet.addListener(object : Animator.AnimatorListener {
            override fun onAnimationEnd(p0: Animator?) {
                if (!isReversed!!) return

                val isChanged = img.tag as Boolean
                if (!isChanged) {
                    img.setImageResource(R.drawable.x02)
                } else {
                    img.setImageResource(R.drawable.z01)
                }
                img.tag = !isChanged
                reverseCard(img, 0.0f, 1.0f, 1.0f, 1.0f)
                isReversed = false
            }
            override fun onAnimationRepeat(p0: Animator?) {}
            override fun onAnimationCancel(p0: Animator?) {}
            override fun onAnimationStart(p0: Animator?) {}
        })
        animatorSet.start()
        isReversed = false
    }
}

https://i.gyazo.com/eb0fa8a9f02966930a0376c7af42408f.gif

これだけでトランプ系のアプリが作れる可能性を感じますね!!!
ただ、scaleだと躍動感感じないのでrotateをうまく使った方がいいかもなので、また考えてみます〜〜!

今回は省略しますが、他にもキーフレームとかも弄れたりするので、ほんとにこれだけでアニメーションマスターになれそうな勢いですな〜!?

実はxmlでも書けるけど、複雑な処理はコードのが楽だと思うよ!

View Animation

  • なんと、、、Androidのバージョンに制限がない!!どこでも使えるすごい
  • 簡単に使える
  • さっきのPropertyAnimationを使う程こだわらない!って場合はこれでささっとつくっちゃいましょう〜!

こっちは手軽にアニメーションを〜って感じなので、xmlで書く方が推奨っぽい!

初めにアニメーション専用のanimフォルダーをres配下に作りましょう!
animフォルダーを右クリックしたら不思議ですねー!
NewのところにAnimation resource fileという項目があるので、そこで作りましょうー!

こんな感じでトップルートはsetタグで始まり、アニメーションさせたい種類のタグをネストさせて、値を設定してあげるだけでおっけーです!

<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:fromDegrees="0.0"
        android:toDegrees="360.0"
        android:pivotX="322"
        android:pivotY="322"
        android:fillAfter="true"
        android:duration="1000"
        android:repeatCount="infinite"/>
</set>


な、なんて楽ちんだ.......
今回は回転アニメーションで、0から360度をx軸y軸共に322の位置を軸に1秒かけて永遠に回るって感じです!

使うタグも少なくてシンプル

  • alpha ->透明度
  • scale -> 拡大or縮小
  • translate -> 位置変更
  • rotate -> 回転
  • interpolator -> 緩急をつけてくれる
  • set -> グルーピング

じゃあ、xmlファイルができたら後はviewに対して適用してあげるだけです!
今回僕はデータバインディングを使っているので気をつけてください!

val anim1 = AnimationUtils.loadAnimation(this, R.anim.set_animate)
mBinding.imageView1.startAnimation(anim1)

https://i.gyazo.com/a098589eb7345c9d52ece506c8dbba1f.gif

うおお〜〜
すごくシンプルにできましたね!

Drawable Animation

これはdrawableリソースを次々と表示する機能です!
パラパラ漫画なんだなーと思えばよいかと!
今度はdrawable配下にルートタグanimation-listでリソースファイルを作ることに注意してください!animフォルダじゃないですよ!

れっつごー

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false"
    android:visible="true">
    <item
        android:drawable="@drawable/gumi_free"
        android:duration="50" />
    <item
        android:drawable="@drawable/gumi_free1"
        android:duration="50" />
    <item
        android:drawable="@drawable/gumi_free2"
        android:duration="50" />
    <item
        android:drawable="@drawable/gumi_free3"
        android:duration="50" />
</animation-list>

アニメーションリソースはgumiちゃんを90度ずつ回転させた画像を4つ用意しました!
ここで見覚えがないのは、oneshotでしょうか?
android:oneshotはfalseならリピートでtrueなら1回のみで終わります!

mBinding.imageView1.setBackgroundResource(R.drawable.drawable_animation)
val frameAnimation = mBinding.imageView1.background as AnimationDrawable
frameAnimation.start()

https://i.gyazo.com/f57404fa4be6a8d69daaf0b420d9d3f2.gif

うむ.....いい感じにくるくるしてるwww
(これは個人的に使う機会なさそうだなぁ)

Physics-based Animations

  • 上記の3つよりも一番新しい!!(2017年3月に追加されたっぽい)
  • 今までのアニメーションってやっぱり現実離れしてるよねー
  • これは物理ベースを盛り込んでいるから、より自然に見せれる!(つよい)

これは少し難しかったので、もう少し勉強しながら更新していこうと思います...(申し訳)

これに関してはここを見て、こんな感じのものなんだなーということさえ、掴んでいただければと...!!!
qiita.com


Lotties

さて、今までざっとアニメーションを色々見てきたわけですが、なんか違うんですよね。。。

僕が求めていたものと違う...!!!!!


うーむとなりながらも色々探し、ようやく見つけました!
airbnb.design

  • airbnbの神ライブラリ
  • After Effectsで作成したアニメーションをjsonに変換して読み込む
  • 誰でもハイクオリティなアニメーション再現が可能(らしい)
  • Android, iOS, React Nativeに対応している

これは楽しみ...!!!
れつごー

導入

dependencies {  
  compile 'com.airbnb.android:lottie:2.3.0'
}

main配下にassetsフォルダーを作成して、そこにjsonファイルをぶち込む
ちなみにアニメーションのjsonファイルの作り方はAfter Effectsにbodymovinというものを導入して、うんやかんやせなあかんらしい...(わからん)

でも大丈夫!!!!!
www.lottiefiles.com

色んなアニメーションがjsonで配られている専用サイトがありました!!!!
ここで試してみよう

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <RelativeLayout
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.gumio_inf.lottiesample.MainActivity">
        <com.airbnb.lottie.LottieAnimationView
            android:id="@+id/animation_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:lottie_fileName="ImThirsty.json"
            app:lottie_loop="true"
            app:lottie_autoPlay="true" />
    </RelativeLayout>
</layout>

コード何も書いてないです
xmlのapp:lottie_fileNameのとこにjsonファイル指定しただけです

実行してみましょう!

https://i.gyazo.com/6f69beb60e046b1b1310cc1c0be60b26.gif

ぎゃあああああああああああああああああああ

これです!!!!!この滑らかにアイコンがウニョウニョするのを求めていた!!!!

普通にImageViewと同じような感じで使えるっぽい(すごい)

でも配布されているやつじゃなくて、自分で何か作りたい....
そんな人はbodymovin頑張ってください..(学習コスト高そう)


と思っているときに何やら気になる話が...github.com

これは。。。。
SVGアニメーションアイコンを作ることが可能っぽい...??

つい先月くらいに日本の方が海外のカンファレンスに行っている時に反応していたのを見かけた情報です
まだまだ新しい情報で使い方が全くわからん...と思ったら

qiita.com

最高かよ!!!!!!!!!

つい昨日じゃないですか!
また近々、Physics Based Animationと共に触ってみようと思います


最近のアニメーションはしゅごい....(小並感)