棚の上のAndroidのアニメーション(パート1.基本アニメーション)

みなさんこんにちは!



今日は、Androidのアニメーションについて少しお話したいと思います。 誰にとっても明らかな事実は、アニメーションがアプリケーションを装飾できるということです。 しかし、私は彼らがもっともっとできると信じています。 まず、優れたアニメーションは、控えめなグラフィックでも、アプリケーションをまったく新しいレベルに引き上げることができます。 2つ目は、ユーザーと通信するための追加のツールです。これにより、注意を集中したり、アプリケーションの仕組みを提案したりできます。しかし、これは別の大きなトピックです。



今日は、アニメーションを作成するためのツールについて説明します。 残念ながら、Androidには何かをアニメートする方法がたくさんあり、最初は混乱するのが非常に簡単です。 最も一般的な分類を提供し、ドキュメントへのリンクのみを残すようにします。 チュートリアルはたくさんあります。 この記事が私の頭の中の棚にすべてを置き、必要に応じてアニメーションを作成し、最も適切な方法を選択するのに役立つことを願っています。



パート1.基本的なアニメーション

パート2.複雑なアニメーション

パート3.「低レベル」アニメーション

パート4.遷移アニメーション

パート5.アニメーションを操作するためのライブラリ



パート1.基本的なアニメーション



1.フレームごと



画像



世界で最初のアニメーションがそのように作成されたと思いますが、この機能はまだAndroidで利用できます。



必要なのは、各フレームへのリンクを含むxmlを作成することだけです。



<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true"> <item android:drawable="@drawable/explosion_1" android:duration="15" /> <item android:drawable="@drawable/explosion_2" android:duration="15" /> <item android:drawable="@drawable/explosion_3" android:duration="15" /> ... </animation-list>
      
      





アニメーションを開始します(以下、すべての例はKotlinで提供されます)。

 val animation = image.drawable as AnimationDrawable animation.start()
      
      





•アプリケーション:



複雑なアニメーショングラフィックス。サイズは小さく、外部エディターで準備されています。



•利点:



複雑なエフェクトを実現する機能



•欠点:



高いリソース消費。その結果、OutOfMemoryを取得する機能を備えたアプリケーションへの非常に高価なインポート。 何らかの理由で多数のフレームを表示する必要がある場合、メモリに画像を徐々にロードして実装を作成する必要があります。 しかし、そうしなければならない場合、おそらくビデオに頼る方が簡単でしょうか?



2.オブジェクトのプロパティのアニメーション(別名プロパティアニメーター)



画像



数ピクセルを横に移動するか、透明度を変更して互いに非常に類似した100万フレームを生成する必要がない場合、Animatorが助けになります。 実際、これを使用すると、オブジェクトのプロパティをアニメーション化できます。



基本抽象クラスはアニメーターと呼ばれ、いくつかの子孫があります。これは私たちにとって重要です。



ValueAnimator-任意のプロパティをアニメーション化できます

ObjectAnimator-ValueAnimatorを継承し、Viewプロパティをアニメーション化するためのシンプルなインターフェイスを備えています。

ViewPropertyAnimator-ビューをアニメーション化するための別の便利なインターフェイスを提供します。 Animatorから継承されず、View :: animate()メソッドで使用されます



上記のアニメーションは、コードのように記述できます。



 val animationX = ObjectAnimator.ofFloat(card, "scaleX", 1F) val animationY = ObjectAnimator.ofFloat(card, "scaleY", 1F) val set = AnimatorSet() set.play(animationX) .with(animationY) set.duration = DURATION set.interpolator = DecelerateInterpolator() set.start()
      
      





XMLで( animator/open_animator.xml



):



 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="together"> <objectAnimator android:duration="250" android:propertyName="scaleX" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> <objectAnimator android:duration="250" android:propertyName="scaleY" android:valueTo="1" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> </set>
      
      





 val set = AnimatorInflater.loadAnimator(context, R.animator.open_animator) as AnimatorSet set.setTarget(card) set.start()
      
      





ビューステート間の遷移のアニメーションを記述することもできます。これにより、任意のビューのステート間のアニメーション化された遷移を簡単に作成できます。 ビューステートが変更されると、XMLで記述されたアニメーションが自動的に開始されます。

animator/state_animator.xml







 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="true"> <set android:ordering="together"> <objectAnimator android:duration="250" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="scaleX" android:valueTo="1" android:valueType="floatType"/> <objectAnimator android:duration="250" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="scaleY" android:valueTo="1" android:valueType="floatType"/> </set> </item> <item android:state_enabled="false"> <set android:ordering="together"> <objectAnimator android:duration="250" android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="scaleX" android:valueTo="0" android:valueType="floatType"/> <objectAnimator android:duration="250" android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="scaleY" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector>
      
      





 <View ... android:stateListAnimator="@animator/state_animator"> </View>
      
      







•アプリケーション:



Viewオブジェクトとそのパラメーターのアニメーション

その他のパラメーターのアニメーション



•利点:



絶対に普遍的



•欠点:



ある程度リソースを消費します。



3.ビューアニメーション(別名ビューアニメーション)



Animatorの前は、Androidにはアニメーションしかありませんでした。 主な欠点は、ビューのビューのみをアニメーション化し、実際にそのプロパティを変更しなかったことです。 したがって、要素の動きをアニメーション化する場合は、アニメーションの最後に、そのプロパティも変更する必要があります。 多少複雑なアニメーションが必要な場合や、アニメーション時にクリックをキャッチする必要がある場合、何らかの方法でこのアプローチはあまり便利ではありません。



アニメーションはコードのように実行できます:



 val anim = ScaleAnimation(0F, 1F, 0F, 1F, 0F, card.measuredHeight.toFloat()) anim.duration = DURATION anim.interpolator = DecelerateInterpolator() anim.fillAfter = true card.startAnimation(anim)
      
      





XMLと同様(構文はAnimatorのxmlとは異なることに注意してください):

anim/open_animation.xml







 <?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="250" android:fillAfter="true" android:fromXScale="0" android:fromYScale="0" android:interpolator="@android:anim/decelerate_interpolator" android:pivotX="0" android:pivotY="100%" android:toXScale="1" android:toYScale="1"/>
      
      





 val animation = AnimationUtils.loadAnimation(context, R.anim.open_animation) card.startAnimation(animation)
      
      







•アプリケーション:



APIがAnimatorの使用を許可しない場合。



•利点:



利用できません



•欠点:



廃止されたAPI。ビューのみを変更します。



4.ベクトルリソースのアニメーション(別名AnimatedVectorDrawable)



画像



私の意見では、Androidアニメーションで最も興味深い部分です。 比較的小さな力で複雑で興味深い効果を実現できます。 Androidのアイコン変換はそのようにして行われます。



VectorDrawableは、Path要素とGroup要素で構成されます。 アニメーションの作成は、これらの要素への動きを登録することになります。 上の写真のAndroidのコードは次のようになります。



たくさんのコード
drawable/hello_android.xml





 <?xml version="1.0" encoding="utf-8"?> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/enabled" android:drawable="@drawable/hello_android_enabled" android:state_enabled="true"/> <item android:id="@+id/disabled" android:drawable="@drawable/hello_android_disabled"/> <transition android:drawable="@drawable/hello_android_waving" android:fromId="@id/enabled" android:toId="@id/disabled"/> <transition android:drawable="@drawable/hello_android_stay_calm" android:fromId="@id/disabled" android:toId="@id/enabled"/> </animated-selector>
      
      





drawable/hello_android_enabled.xml





 <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:rotation="-160" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector>
      
      





drawable/hello_android_disabled.xml







 <vector xmlns:android="http://schemas.android.com/apk/res/android" android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector>
      
      





drawable/hello_android_waving.xml







 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="32dp" android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> <path android:name="path_1" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z" android:fillColor="#000000"/> <group android:name="group" android:pivotX="20.5" android:pivotY="17"> <path android:name="path" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16" android:fillColor="#000"/> </group> </vector> </aapt:attr> <target android:name="group"> <aapt:attr name="android:animation"> <set> <objectAnimator android:propertyName="rotation" android:duration="300" android:valueFrom="0" android:valueTo="-170" android:valueType="floatType" android:interpolator="@android:anim/decelerate_interpolator"/> <objectAnimator android:propertyName="rotation" android:startOffset="300" android:duration="200" android:valueFrom="-170" android:valueTo="-160" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> <objectAnimator android:propertyName="rotation" android:startOffset="500" android:duration="200" android:valueFrom="-160" android:valueTo="-170" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> <objectAnimator android:propertyName="rotation" android:startOffset="700" android:duration="200" android:valueFrom="-170" android:valueTo="-160" android:valueType="floatType" android:interpolator="@android:interpolator/fast_out_slow_in"/> </set> </aapt:attr> </target> </animated-vector>
      
      





drawable/hello_android_stay_calm.xml







 <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"> <aapt:attr name="android:drawable"> <vector android:name="vector" android:width="32dp" android:height="32dp" android:viewportHeight="32" android:viewportWidth="32"> <path android:fillColor="#000000" android:pathData="M 15 13 L 14 13 L 14 12 L 15 12 M 10 13 L 9 13 L 9 12 L 10 12 M 15.53 10.16 L 16.84 8.85 C 17.03 8.66 17.03 8.34 16.84 8.14 C 16.64 7.95 16.32 7.95 16.13 8.14 L 14.65 9.62 C 13.85 9.23 12.95 9 12 9 C 11.04 9 10.14 9.23 9.34 9.63 L 7.85 8.14 C 7.66 7.95 7.34 7.95 7.15 8.14 C 6.95 8.34 6.95 8.66 7.15 8.85 L 8.46 10.16 C 6.97 11.26 6 13 6 15 L 18 15 C 18 13 17 11.25 15.53 10.16 M 3.5 16 C 2.672 16 2 16.672 2 17.5 L 2 24.5 C 2 25.328 2.672 26 3.5 26 C 4.328 26 5 25.328 5 24.5 L 5 17.5 C 5 16.672 4.328 16 3.5 16 M 6 26 C 6 26.552 6.448 27 7 27 L 8 27 L 8 30.5 C 8 31.328 8.672 32 9.5 32 C 10.328 32 11 31.328 11 30.5 L 11 27 L 13 27 L 13 30.5 C 13 31.328 13.672 32 14.5 32 C 15.328 32 16 31.328 16 30.5 L 16 27 L 17 27 C 17.552 27 18 26.552 18 26 L 18 16 L 6 16 L 6 26 Z"/> <group android:name="arm" android:pivotX="20.5" android:pivotY="17" android:rotation="-160"> <path android:name="path" android:fillColor="#000" android:pathData="M 20.5 16 C 19.672 16 19 16.672 19 17.5 L 19 24.5 C 19 25.328 19.672 26 20.5 26 C 21.328 26 22 25.328 22 24.5 L 22 17.5 C 22 16.672 21.328 16 20.5 16"/> </group> </vector> </aapt:attr> <target android:name="arm"> <aapt:attr name="android:animation"> <set> <objectAnimator android:duration="300" android:interpolator="@android:anim/decelerate_interpolator" android:propertyName="rotation" android:valueFrom="-160" android:valueTo="0" android:valueType="floatType"/> </set> </aapt:attr> </target> </animated-vector>
      
      







XMLを手動で記述しないようにするには、 オンラインツールを使用できます



API 25から、ベクトルアニメーションはRenderThreadでレンダリングされるため、UIスレッドに何かを読み込んだとしても(そうしないのですか?)、アニメーションは引き続きスムーズに再生されます。



•アプリケーション:



アイコン

アニメーション効果



•利点:



性能



•欠点:



アニメーションの時点を手動で制御する方法はありません(つまり、実際にはsetCurrentTimeのようなメソッドはありません)



ここですべての例を見て勉強できます



All Articles