Android 用の最も完全なアニメーションの説明

Android のアニメーションは、ビュー アニメーション、フレーム アニメーション、属性アニメーションの 3 種類に分類されます。

アニメーションを見る

ビューアニメーションとはアニメーションの対象となるのはビューアニメーションのみで、これをビューアニメーションと呼びます。ビュー アニメーションには、 TranslateAnimation (移動)、ScaleAnimation (ズーム)、RotateAnimation (回転)、AlphaAnimation (透明)の 4 種類があります。また、 AnimationSet (結合アニメーション)もあり、これらはすべてアニメーションクラスを継承します。ビューのアニメーションは、ビューのプロパティを変更するのではなく、Convas 関連の設定によって実現されるため、ビューは変換されますが、クリック イベントは変化しないという問題が発生することに注意してください。

すべてのアニメーションの原点座標は、ビューの左上の頂点を基準にしていることに注意してください。

ビュー アニメーションを実装するには、動的コードと XML ファイルの実装の 2 つの方法があります。再利用性の高いxmlの使用を推奨します。

 xml で使用する場合は、xml ファイルを作成する必要があります。ファイル パスは: res/anim/filename.xmlです。

翻訳アニメーションアニメーション

コード:

fromXType が指定されていない場合、デフォルトは ABSOLUTE です。

 施工方法は上記の3通りあります。

formXType : fromXValue をどのように解釈するかを指定します。次の 3 つのモードがあります。

ABSOLUTE //絶対値、単位はpx
RELATIVE_TO_SELF //それ自体に対する相対、つまり fromXValue* 自体の幅
RELATIVE_TO_PARENT //親クラスに対して相対的、つまり親クラスのfromXvalue*width

よく使用されるプロパティ:

継続時間: アニメーションの継続時間、デフォルトは 0 で、即時を意味します。
fillAfter: アニメーション実行後、終了位置を維持するかどうか
fillBefore: アニメーション終了後、開始位置を維持するかどうか
repeatCount: アニメーションを繰り返します。デフォルトは 1 回です。-1 は無効なループを表します。
repeatMode:アニメーション繰り返しモードAnimation.REVERSE(アニメーション終了後に逆方向に繰り返す)Animation.RESTART(毎回やり直す)
補間: アニメーション補間、時間の経過に伴う変化、アニメーション プロパティの変化率
リセット: アニメーションをリセット
setStartOffset: 開始時間に対するアニメーションの遅延時間、offset-offset
setStartTime: アニメーション実行の特定の時間を設定します。単位はミリ秒の開始時間です。
cancel(): アニメーションの停止とビューのアニメーションの停止を同時に行います。clearAnimation() を使用することもできます。違いは、cancel は指定されたアニメーションを停止し、clearAnimation() は現在のビューに影響を与えるアニメーションを停止することです。 onAnimationEnd メソッドをコールバックします。
XML 実装:

まずresにanimフォルダを作成し、 

アニメーション オプションを選択します。名前は固定アニメーションのみにすることができます。 

作成後、右クリックしてXMLアニメーションを作成します

slide_1.xml を作成する  

第一种写法:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    >
<translate
    android:duration="500"
    android:fillAfter="true"
    android:fromXDelta="0"
    android:toXDelta="200"
    ></translate>
</set>

<set>是animationSet的xml写法,如果这样写的话,会发现一个问题,就是在<tramslate  标签里面,基本不会提示duration等,这个时候把xmlns:android="http://schemas.android.com/apk/res/android"引用写到<translate>标签中就可以了。

第二种写法:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fillAfter="true"
    android:fromXDelta="0"
    android:toXDelta="200"
    >
</translate>

xml にはformXType または formYType属性がありません。では、それらをどのように表現すればよいでしょうか?

android:toYDelta="50" 修飾子なし、ABSOLUTE を表し、単位は px

android:toYDelta="50%" // %代表RELATIVE_TO_SELF

android:toYDelta="50%p" // %p 代表 RELATIVE_TO_PARENT

使用:

      val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_1)
                it.startAnimation(loadAnimation)

監視を設定します。

     loadAnimation.setAnimationListener(object :AnimationListener{
                override fun onAnimationStart(animation: Animation?) {
                }

                override fun onAnimationEnd(animation: Animation?) {
                }

                override fun onAnimationRepeat(animation: Animation?) {
                }

            })

スケールアニメーションアニメーション

  コード:

 パラメータの説明:

fromX: 独自の X 軸の長さの 0.5 倍からスケーリングを開始します(スケーリングの px 値には特に注意しません)。たとえば: fromX= 0.5 は、独自の X 軸の長さの 0.5 倍から開始することを意味します。

tox: スケーリングは、それ自体の x 軸の長さの何倍で終了します。たとえば、: toX = 2.0 は、x 軸のスケーリングがそれ自体の x 軸の長さの 2 倍で終了することを意味します。

formY: 自身の Y 軸の長さの 0.5 倍からスケーリングを開始します。例: fromY=0.5 は、自身の Y 軸の長さの 0.5 倍から開始することを意味します。

toY: Y 軸の長さが何倍にスケーリングされるか。たとえば、toY=2.0。これは、Y 軸が Y 軸の長さの 2 倍にスケーリングされることを意味します。

ピボット(中心点)

pivotX: 制御軸 X の位置を基準にしてスケーリングを開始します。

pivotY: 制御軸 y の位置を基準にしてスケーリングを開始します。

pivotXType: pivotx 値の意味を説明します。デフォルトは ABSOLUTE です

pivotYType: ピボット値の意味を説明します。デフォルトは ABSOLUTE です

ズームするときは、pivotx と pivoty を中心点として使用して、両側を同時にズームすることに注意してください。

XML 実装:
<?xml version="1.0" encoding="utf-8"?>
<set
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<scale
    android:duration="500"
    android:fillAfter="true"
    android:fromXScale="1"
    android:toXScale="0.5"
    android:fromYScale="1"
    android:toYScale="0.5"
    android:pivotY="50%"
    android:pivotX="50%"
    ></scale>
</set>
切记,不要在xml中添加float的修饰符 f,不然编译不过
如:
<scale
    android:duration="500"
    android:fillAfter="true"
    android:fromXScale="1"
    android:toXScale="0.5f"   //这样编译不过
    android:fromYScale="1"
    android:toYScale="0.5"
    android:pivotY="50%"
    android:pivotX="50%"
    ></scale>

RotateAnimation回転アニメーション

コード:

 formDegrees: どの角度から回転を開始するか

toDegrees: 回転は何度で終了しますか?

pivotX:X軸回転中心位置

pivoty: y 軸上の回転中心位置

pivotXtype: pivotx の意味を説明します。デフォルトは ABSOLUTE です

AlphaAnimation 透明アニメーション

    /**
     * Constructor to use when building an AlphaAnimation from code
     * 
     * @param fromAlpha Starting alpha value for the animation, where 1.0 means
     *        fully opaque and 0.0 means fully transparent.
     * @param toAlpha Ending alpha value for the animation.
     */
    源码的注解已经说明,透明度的值是0.0-1.0
    public AlphaAnimation(float fromAlpha, float toAlpha) {
        mFromAlpha = fromAlpha;
        mToAlpha = toAlpha;
    }
コード:
     val alphaAnimation = AlphaAnimation(1f, 0f).
               apply {
                   duration =500
               }
              it.startAnimation(alphaAnimation)
XML実装

アニメーション -> 新規 -> アニメーション リソース ファイル ->

 この時、durationなど書けないコードが多いことが分かりましたが、この時はsetタグを外層で囲んで値をコピーし、<set>タグを削除すればOKです。

<?xml version="1.0" encoder="utf-8"?> 
<alpha xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fromAlpha="1" 
   android:duration ="500"
    アンドロイド:toAlpha="0.5" 
    />

アニメーションを組み合わせたアニメーションを設定します

複数のアニメーションを組み合わせる

コード

AnimationSet の addAnimation メソッドを通じて実行されます。

val apply = AnimationSet(true).apply {
    addAnimation(RotateAnimation(
        0f, -90f, Animation.RELATIVE_TO_SELF, 0.5f,
        Animation.RELATIVE_TO_SELF, 0.5f
    ).apply {
        duration = 300
    })
    addAnimation(AlphaAnimation(1.0f, 0.3f).apply {
        duration = 300
        startOffset = 300
    })
}
it.startAnimation(apply)
XMLで実行
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:interpolator="@android:anim/linear_interpolator" //动画集合的插值器
    android:shareInterpolator="true"  
   //表示动画集合是否共享一个插值器,如果不指定插值器,那么子动画就需要自己指定插值器,或者使用默认的
    android:fillAfter="true"
    >
<rotate
    android:fromDegrees="0"
    android:toDegrees="90"
    ></rotate>

    <alpha
        android:fromAlpha="1"
        android:duration="800"  //子类的设置的时间会替换动画集合的时间
        android:toAlpha="0.0"
        ></alpha>

</set>

ビューに合計 3 つのアニメーションを実装する方法 1 つのアニメーションが終了すると、別のアニメーションが実行されますか?

プロパティアニメーションには順序付け属性がありますが、ビューアニメーションは一緒に実行され、順序付け属性はありません。

そうすれば合格できるよ

実行する startOffset 属性。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <translate
        android:fromXDelta="0"
        android:toXDelta="200"
        android:duration="500"
        ></translate>
    <rotate
        android:startOffset="500"
        android:fromDegrees="0"
        android:toDegrees="180"
        android:pivotX="100%"
        android:pivotY="50%"
        android:duration="500"
        ></rotate>

    <alpha
        android:startOffset="1000"
        android:fromAlpha="1"
        android:toAlpha="0.2"
        android:duration="500"
        ></alpha>


</set>

レイアウトアニメーション

このアニメーションがこの ViewGroup に指定されている場合、他のすべてのサブ要素が表示されるときにこのアニメーション効果が適用されます。layoutAnimation は個別のアニメーションを指すのではなく、手段を指します。ビューアニメーションとしても見ることができます。

XMLの書き方

animフォルダーにlayoutAnimationタイプのファイルを作成します。

lyanimation.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/slide_1"   
    android:animationOrder="normal"
    android:delay="0.5"
    >
</layoutAnimation>

animation //引用的view动画
animationOrder //子元素执行动画的顺序,有三种选项:normal、reverse和random,其中normal表示顺
序显示,即排在前面的子元素先开始播放入场动画;reverse表示逆向显示,即排在后面的
子元素先开始播放入场动画;random则是随机播放入场动画。
delay //表示子元素开始动画的时间延迟,比如子元素入场动画的时间周期为300ms,那么0.5
表示每个子元素都需要延迟150ms才能播放入场动画。总体来说,第一个子元素延迟
150ms开始播放入场动画,第2个子元素延迟300ms开始播放入场动画,依次类推。

 スライド_1.xml

<?xml version="1.0" encoding="utf-8"?>
<set
    android:duration="300"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
<translate
    android:fromXDelta="-100%"
    android:toXDelta="0"
    ></translate>
</set>

ViewGroup の android:layoutAnimation="@anim/lyanimation" によって参照されます。

 <LinearLayout
        android:gravity="center_horizontal"
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:id="@+id/tv_click_12"
        android:layout_marginBottom="@dimen/dp_300"
        android:layoutAnimation="@anim/lyanimation" //引用
        android:layout_height="wrap_content">

        <TextView
            android:background="@drawable/img"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_marginTop="@dimen/dp_30"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_1"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_2"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
        <TextView
            android:layout_marginTop="@dimen/dp_30"
            android:background="@drawable/img_3"
            android:layout_width="400px"
            android:text="组合动画"
            android:gravity="center"
            android:layout_height="100px"></TextView>
    </LinearLayout>
コードで設定する

これは終了アニメーションであることに注意してください。viewGroup がすでに表示されている場合、クリック イベントを通じてこのアニメーションを設定しても効果はありません。

        val tv_click_12 = findViewById<LinearLayout>(R.id.tv_click_12);//获得viewGroup
 
     
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_1) //加载view动画
val LayoutAnimationController = LayoutAnimationController(loadAnimation).apply { //创建LayoutAnimationController
 delay = 0.5f
order = LayoutAnimationController.ORDER_NORMAL
            }
            tv_click_12.layoutAnimation = LayoutAnimationController  //设置
      

効果は次の図に示すとおりです。

アクティビティ切り替え効果 

アクティビティ ジャンプにはデフォルトのアニメーション効果がありますが、このアニメーションをカスタマイズすることもできます。主に

public void overridePendingTransition(int enterAnim, int exitAnim) { 
    ActivityClient.getInstance().overridePendingTransition(mToken, getPackageName(), 
            enterAnim, exitAnim); 
}

こちらです。このメソッドを有効にするには、startActivity(intent) またはfinish() の後に呼び出す必要があります。

enterAnim - アクティビティを開くときに必要なアニメーション リソース ID
exitAnim - アクティビティが一時停止されるときに必要なアニメーション リソース ID
フラグメントの 切り替えもアニメーション化可能 FragmentはAPI 11で新たに導入されたクラスのため、互換性の観点から
静電容量については、 support-v4互換パッケージ を使用する必要があります 。この場合、 FragmentTransaction を使用できます。
setCustomAnimations () メソッドを使用して切り替えアニメーションを追加します。この切り替えアニメーションは View アニメーションである必要があります。
プロパティアニメーションも API 11 で新たに導入されたため、プロパティアニメーションは使用できません。 アクティビティ を与える他の方法はありますか?
Fragment は 切り替えアニメーションを追加しますが、それらのほとんどには互換性の問題があり、以前のバージョンでは使用できないため、
利用価値が高いので、ここでは一つ一つ紹介しません。

フレームアニメーション

フレーム アニメーションでは、映画の再生と同様に、一連の事前定義された画像が順番に再生されます。ビューアニメーションとは異なり、フレームアニメーションを使用するためにAnimationDrawableクラスが用意されています。AnimationDrawableはDrawableに属しているので、ドローアブルフォルダー内で直接右クリック→新規→ドローアブルリソースファイル→

XMLファイルを作成する

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"  oneshot = tru表示执行一遍,false是一直重复执行
    >
<item android:duration="200" android:drawable="@drawable/img"></item>
    <item android:duration="200" android:drawable="@drawable/img_1"></item>
    <item android:duration="200" android:drawable="@drawable/img_2"></item>
    <item android:duration="200" android:drawable="@drawable/img_3"></item>
</animation-list>

 ビューを設定して北京カラーを設定する

コード内で使用:

      val mAnimationDrawable = findViewById<View>(R.id.tv_click_11).background as AnimationDrawable
            mAnimationDrawable.start()

それでおしまい。

プロパティアニメーション

プロパティ アニメーションはビュー アニメーションを拡張し、オブジェクトでなくても、あらゆるオブジェクトで動作します。プロパティ アニメーションは、移動、拡大縮小、回転、透明度の 4 つの単純な変更に限定されません。

プロパティ アニメーションには、ValueAnimator、ObjectAnimator、AnimtorSet が含まれます。これら 3 つを使用すると、複雑なアニメーションを実現できます。

属性アニメーションを理解する前に、次の 2 つのクラスを理解する必要があります。

interpolator interpolator、このビューアニメーションにもそれがあります。TypeEvaluator エバリュエーター

補間器の機能は、時間の経過に伴う現在の属性値の変化の割合を計算することです。

Android にはいくつかの補間機能が組み込まれています

LinearInterpolator (線形補間器: 均一アニメーション)

AccelerateDecelerateInterpolator (加速および減速補間: アニメーションは両端で遅く、中間で速くなります)

DecelerateInterpolator (減速補間: アニメーションがどんどん遅くなります)

TypeEvaluator の機能は、現在の属性変更のパーセンテージに基づいて、変更された属性値を計算することです。

IntEvaluator (整数プロパティ用)

FloatEvaluator (浮動小数点プロパティ用)
ArgbEvaluator (タイプ color の属性の場合)
プロパティのアニメーションがターゲット (非 int、
float Color )、型推定器をカスタマイズする必要があります。
エスティメーターをカスタマイズする方法:
public class IntEvaluator implements TypeEvaluator<Integer> {
public Integer evaluate(float fraction,Integer startValue,Integer
endValue) {
int startInt = startValue;
return (int)(startInt + fraction * (endValue -startInt));
}
}

​​​​​​​

オブジェクトアニメーター

objectAnimator はオブジェクト用です。objectAnimator は ValueAnimator のサブクラスであり、次の重要なメソッドがあります。

ObjectAnimator.ofInt()   
ObjectAnimator.ofFloat() 
ObjectAnimator.ofArgb() 
ObjectAnimator.ofObject() 

//android は、int、float、argb などのデフォルトの評価子を提供します。 ObjectAnimator.ofObject() を使用する場合は、評価をカスタマイズする必要がありますデバイス。この記事を参照してくださいAndroid アニメーション学習 (3): カスタム プロパティ アニメーション - Jianshu

 
public static ObjectAnimator ofInt(Object target, String propertyName, int...values) { 
    ObjectAnimator anim = new ObjectAnimator(target, propertyName); 
    anim.setIntValues (値);
    アニメーションを返します; 
}

target: アニメーションのオブジェクト

propertyName: 変更するプロパティの名前 アニメーションを実行すると、このプロパティの set メソッドが継続的に呼び出されます。

int... value: 属性値の変化、配列です。例: 透明度、0->1->0

属性アニメーションの原理は、属性値を一定の速度で動的に変更してアニメーションの効果を実現することであるため、属性アニメーションを設定するには次の 2 つの条件を満たす必要があります。

1: AB 属性に属性アニメーションを設定する場合は、それを満たす必要があります。この属性には setAB メソッドがあり、開始値が設定されていない場合は getAB メソッドが必要です。属性アニメーションは、これを通じて初期値を取得します。方法。

2. 属性アニメーションを実行する際の属性値の変更は UI に反映される必要があり、そうでない場合は効果がありません。

例: 属性を使用して次の効果を実現する方法。

解析コード: 左の図はレイアウトを展開した状態と折りたたんだ状態で、赤いレイアウトをクリックすると左の図が表示されるようにすることができます。

この効果を実現するには、marginLeft を変更します。

アニメーション属性が満たさなければならない 2 つの条件によると、左側の ImageView にはmarginLeft属性がないことがわかりますでは、上記 2 つの条件を満たさない属性でアニメーションを実行する問題を解決するにはどうすればよいでしょうか? 公式の解決策は次のとおりです。

  1. 元のオブジェクトをラップするオブジェクトのラッパー クラスを提供します。そのような属性がない場合は、この属性を間接的に提供し、get メソッドと set メソッドを提供します。
  2. ValueAnimator を使用してアニメーション プロセスを監視し、プロパティを自分で変更します。

 動的コード:

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:id="@+id/ln_content"
    tools:context=".AnimationActivity2">
    <TextView
        android:id="@+id/slide_s"
        android:layout_width="400px"
        android:text="点击显示全"
        android:background="@drawable/img_2"
        android:layout_height="match_parent"></TextView>
    <TextView
        android:text="点击展开和关闭"
        android:layout_width="50dp"
        android:id="@+id/click_button"
        android:background="@color/color_f74e00"
        android:layout_height="match_parent"></TextView>
    <HorizontalScrollView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="horizontal"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="200dp"
            android:text="1"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="2"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="3"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="4"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="5"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="6"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:text="7"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="8"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
        <TextView
            android:layout_width="200dp"
            android:text="9"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="#ffffff"
            android:layout_margin="@dimen/dp_20"
            android:background="#00b5ad"
            android:layout_height="match_parent"/>
    </LinearLayout>


    </HorizontalScrollView>


</LinearLayout>
コード:
ラッパークラスを使用して実装します。

ラッパークラスを作成します: SlideWrapper

    class SlideWrapper(val mSlide: View) {
        private var marginLeft :Int  //提供这个属性
        get() {   //重新这个属性的get方法
            return (mSlide.layoutParams as LinearLayout.LayoutParams).leftMargin
        }
        set(value) {  //重写这个属性的set方法,满足属性值的改变会体验在ui效果上
          
            val apply = (mSlide.layoutParams as LinearLayout.LayoutParams).apply {
                leftMargin = value
            }
            mSlide.layoutParams = apply
        }

    }

var isExpand:Boolean = true  //定义一个字段记录展开和收起的状态
 val slideView  = SlideWrapper(slide_s)
findViewById<View>(R.id.click_button).setOnClickListener {
              it.isEnabled = false
              if (isExpand){
                  //这是属性动画
                  ObjectAnimator.ofInt(slideView,"marginLeft",-400).apply {
                      duration = 500
                    addListener(object :AnimatorListener{
                        override fun onAnimationStart(animation: Animator?) {
                        }

                        override fun onAnimationEnd(animation: Animator?) {
                            it.isEnabled = true
                            isExpand = false
                        }

                        override fun onAnimationCancel(animation: Animator?) {
                        }

                        override fun onAnimationRepeat(animation: Animator?) {
                        }

                    })
                      start()
                  }
              }  else{
              
                  ObjectAnimator.ofInt(slideView,"marginLeft",-400,0).apply {
                      duration =500
                      addListener(object:AnimatorListener{
                          override fun onAnimationStart(animation: Animator?) {
                          }

                          override fun onAnimationEnd(animation: Animator?) {
                              it.isEnabled = true
                              isExpand = true
                          }

                          override fun onAnimationCancel(animation: Animator?) {
                          }

                          override fun onAnimationRepeat(animation: Animator?) {
                          }

                      })
                      start()
                  }
              }
        }
ValueAnimatorを使用したアニメーション監視処理の実装

ValueAnimator 自体はオブジェクトに作用しません。つまり、直接使用しても効果はありません。値をアニメーション化できます。アニメーション プロセスを監視し、アニメーション プロセス中にオブジェクトのプロパティ値を変更できます。これは、オブジェクトをアニメーション化することにも相当します。

  slide_s = findViewById<ImageView>(R.id.slide_s)
        findViewById<View>(R.id.click_button).setOnClickListener {
            it.isEnabled = false //防止动画没有执行完,触发点击事件
            if (isOpen){
                //执行关闭动画,我们监听从0到 -400的int值的变化
                ValueAnimator.ofInt(0,-400).apply {
                    duration = 500 //动画执行时间
                    //监听动画的每一帧
                    addUpdateListener(object :AnimatorUpdateListener{
                        override fun onAnimationUpdate(animation: ValueAnimator) {
                            val animatedValue = animation.animatedValue as Int //获得动画当前的值
                            val apply = (slide_s.layoutParams as LinearLayout.LayoutParams).apply {
                                leftMargin = animatedValue
                            }
                          
                        }

                    })
                    //监听动画的执行过程
                    addListener(object :AnimatorListener{
                        override fun onAnimationStart(animation: Animator?) {
                        }

                        override fun onAnimationEnd(animation: Animator?) {
                            it.isEnabled =true
                        }

                        override fun onAnimationCancel(animation: Animator?) {
                        }

                        override fun onAnimationRepeat(animation: Animator?) {
                        }

                    })
                    start()
                }


            }else{
                //执行打开动画
    ValueAnimator.ofInt(-400,0).apply {
        duration =500
        addUpdateListener(object :AnimatorUpdateListener{
            override fun onAnimationUpdate(animation: ValueAnimator) {
                val animatedValue = animation.animatedValue as Int //获得动画当前值
                val apply = (slide_s.layoutParams as LinearLayout.LayoutParams).apply {
                    leftMargin = animatedValue
                }
             
            }

        })

        addListener(object :AnimatorListener{
            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                it.isEnabled =true
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationRepeat(animation: Animator?) {
            }

        })
        start()
    }
            }
        }

ここでは AnimatorUpdateListener を使用します。このリスナーは特別です。アニメーション プロセス全体を監視します。アニメーションは多数のフレームで構成されます。フレームが再生されるたびに、onAnimationUpdate が 1 回呼び出されます。

効果も同様です。

属性アニメーションは、コードを通じて実装されるだけでなく、XML を通じて定義することもできます。プロパティアニメーションはで定義する必要があります

res/animator/ ディレクトリの構文は次のとおりです。
<set
android:ordering=["together" | "sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]/>

</set>
属性动画的各种参数都比较好理解,在XML中可以定义ValueAnimator、ObjectAnimator以及AnimatorSet,其中<set>标签对应AnimatorSet,<Animator>标签对应
ValueAnimator,而<objectAnimator>则对应ObjectAnimator。<set>标签的android:ordering
属性有两个可选值:“together”和“sequentially”,其中“together”表示动画集合中的子动画
同时播放,“sequentially”则表示动画集合中的子动画按照前后顺序依次播放,
android:ordering属性的默认值是“together”。
对于<objectAnimator>标签的各个属性的含义,下面简单说明一下,对于<Animator>
标签这里就不再介绍了,因为它只是比<objectAnimator>少了一个android:propertyName属
性而已,其他都是一样的。
android:propertyName——表示属性动画的作用对象的属性的名称;
android:duration——表示动画的时长;
android:valueFrom——表示属性的起始值;
android:valueTo——表示属性的结束值;
android:startOffset——表示动画的延迟时间,当动画开始后,需要延迟多少毫秒才会
真正播放此动画;
android:repeatCount——表示动画的重复次数;
android:repeatMode——表示动画的重复模式;
android:valueType——表示android:propertyName所指定的属性的类型,
有“intType”和“floatType”两个可选项,分别表示属性的类型为整型和浮点型。另外,
如果android:propertyName所指定的属性表示的是颜色,那么不需要指定
android:valueType,系统会自动对颜色类型的属性做处理。
对于一个动画来说,有两个属性这里要特殊说明一下,一个是android:repeatCount,
它表示动画循环的次数,默认值为0,其中-1表示无限循环;另一个是
android:repeatMode,它表示动画循环的模式,有两个选项:“repeat”和“reverse”,分别表
示连续重复和逆向重复。连续重复比较好理解,就是动画每次都重新开始播放,而逆向重
复是指第一次播放完以后,第二次会倒着播放动画,第三次再重头开始播放动画,第四次
再倒着播放动画,如此反复

 

おすすめ

転載: blog.csdn.net/xueyoubangbang/article/details/132109140