Android自定義View動畫

運行效果:

前言:

Android系統提供了兩個動畫框架:屬性動畫框架和View動畫框架。 兩個動畫框架都是可行的選項,但是屬性動畫框架通常是首選的使用方法,因爲它更靈活,並提供更多的功能。 除了這兩個框架,還可以使用Drawable動畫(即逐幀動畫,AnimationDrawable),它允許你加載Drawable資源並逐幀地顯示它們。

View動畫框架中一共提供了AlphaAnimation(透明度動畫)、RotateAnimation(旋轉動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(平移動畫)四種類型的補間動畫;並且View動畫框架還提供了動畫集合類(AnimationSet),通過動畫集合類(AnimationSet)可以將多個補間動畫以組合的形式顯示出來;當然如果對提供的類型動畫不滿意,可以自定義動畫!

View佈局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnAlpha"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="80dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@color/colorAccent"
        android:text="@string/animation_me"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="30sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnRotate"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@color/colorPrimary"
        android:text="@string/rotate_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnAlpha" />

    <Button
        android:id="@+id/btnTranslate"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@color/colorPrimaryDark"
        android:text="@string/translate_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnRotate" />

    <Button
        android:id="@+id/btnScale"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@android:color/holo_orange_dark"
        android:text="@string/scale_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnTranslate" />

    <Button
        android:id="@+id/btnBlend"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@android:color/background_dark"
        android:text="@string/blend_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="30sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnScale" />

    <Button
        android:id="@+id/btnListener"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@android:color/holo_green_dark"
        android:text="@string/listener_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnBlend" />

    <Button
        android:id="@+id/btnCustom"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        android:background="@android:color/holo_red_light"
        android:text="@string/custom_animation"
        android:textAllCaps="false"
        android:textColor="@android:color/background_light"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnListener" />

</android.support.constraint.ConstraintLayout>

Control層:

 MainActivity.java:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btnAlpha,btnRotate,btnTranslate,btnScale,btnBlend,btnListener,btnCustom;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    public void initView(){
        btnAlpha=findViewById(R.id.btnAlpha);
        btnRotate=findViewById(R.id.btnRotate);
        btnTranslate=findViewById(R.id.btnTranslate);
        btnScale=findViewById(R.id.btnScale);
        btnBlend=findViewById(R.id.btnBlend);
        btnListener=findViewById(R.id.btnListener);
        btnCustom=findViewById(R.id.btnCustom);

        btnAlpha.setOnClickListener(this);
        btnRotate.setOnClickListener(this);
        btnTranslate.setOnClickListener(this);
        btnScale.setOnClickListener(this);
        btnBlend.setOnClickListener(this);
        btnListener.setOnClickListener(this);
        btnCustom.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btnAlpha:
                 //方法一:Java程序配置動畫
//               AlphaAnimation animation=new AlphaAnimation(0,1);//透明度從零到一
//               animation.setDuration(2000);//動畫時長
//               v.startAnimation(animation);//按鈕開啓動畫

                 //方法二:使用佈局文件來配置動畫
                 v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.alpha));
                 break;
            case R.id.btnRotate:
                //方法一:Java程序配置動畫
//               RotateAnimation rotateAnimation=new RotateAnimation(0,360,
//                        Animation.RELATIVE_TO_SELF,0.5f,
//                        Animation.RELATIVE_TO_SELF,0.5f);//零到360度,旋轉點爲控件相對中心
//               rotateAnimation.setDuration(2000);
//               v.startAnimation(rotateAnimation);
                //方法二:使用佈局文件來配置動畫
                 v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate));
                 break;
            case R.id.btnTranslate:
//                TranslateAnimation translateAnimation=new TranslateAnimation(0,200,
//                        0,200);//從原位置向x、y方向各移動200像素
//                translateAnimation.setDuration(2000);
//                v.startAnimation(translateAnimation);
                v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate));
                break;
            case R.id.btnScale:
//                ScaleAnimation scaleAnimation=new ScaleAnimation(0,1,0,1,
//                        Animation.RELATIVE_TO_SELF,0.5f,
//                        Animation.RELATIVE_TO_SELF,0.5f);//縮放從零到一,縮放點相對於自身中心
//                scaleAnimation.setDuration(2000);
//                v.startAnimation(scaleAnimation);
                v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.scale));
                break;
            case R.id.btnBlend:
                //動畫集合類AnimationSet
//                AnimationSet animationSet=new AnimationSet(true);//各動畫共用動畫補間
//                補間動畫是一種設定動畫開始狀態、結束狀態,其中間的變化由系統計算補充。
//                animationSet.setDuration(2000);
//
//                RotateAnimation rotateAnimation=new RotateAnimation(0,360,
//                        Animation.RELATIVE_TO_SELF,0.5f,
//                        Animation.RELATIVE_TO_SELF,0.5f);
//                rotateAnimation.setDuration(1000);
//                animationSet.addAnimation(rotateAnimation);//集合中添加子動畫
//                ScaleAnimation scaleAnimation=new ScaleAnimation(0,1,0,1,
//                        Animation.RELATIVE_TO_SELF,0.5f,
//                        Animation.RELATIVE_TO_SELF,0.5f);
//                scaleAnimation.setDuration(1000);
//                animationSet.addAnimation(scaleAnimation);
//                v.startAnimation(animationSet);
                v.startAnimation(AnimationUtils.loadAnimation(MainActivity.this,R.anim.blend));
                break;
            case R.id.btnListener:
                Animation animation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.blend);
                animation.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                        Toast.makeText(MainActivity.this,"動畫開始!",Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        Toast.makeText(MainActivity.this,"動畫結束!",Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                        //動畫重複執行
                    }
                });
                v.startAnimation(animation);
                break;
            case R.id.btnCustom:
                CustomAnimation customAnimation=new CustomAnimation();
                v.startAnimation(customAnimation);
        }
    }
}

 CustomAnimation.java:

public class CustomAnimation extends Animation {

    //動畫初始化,用來設置動畫的基本屬性
    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        setDuration(2000);//設置動畫時長
    }

    //該方法用來實現動畫,
    // interpolatedTime表示插值器的時間因子,補間時間,取值範圍0-1
    // t一個矩陣的封裝類,實現動畫就是利用矩陣來計算的
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
        //t.setAlpha(interpolatedTime);//透明效果

        //Matrix可將一個點映射到另一個點,矩陣中包含了處理縮放、透視以及平移的區域,從而可用於控制實現平移、縮放、旋轉等動畫效果。
        //t.getMatrix().setTranslate(interpolatedTime*200,interpolatedTime*200);//平移效果

        t.getMatrix().setTranslate((float) (Math.sin(interpolatedTime*20)*50),0);//使用周期函數實現搖頭效果
    }
}

資源配置文件:

alpha.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1"
    android:duration="2000">
</alpha>

rotate.xml

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:duration="2000"
    android:pivotX="50%"
    android:pivotY="50%">

</rotate>

scale.xml

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:toXScale="1"
    android:fromYScale="0"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="2000">

</scale>

translate.xml

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="200"
    android:fromYDelta="0"
    android:toYDelta="200"
    android:duration="2000">

</translate>

blend.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="true"
    android:duration="2000">

    <rotate android:fromDegrees="0"
        android:toDegrees="360"
        android:duration="1000"
        android:pivotX="50%"
        android:pivotY="50%">
    </rotate>
    <scale android:fromXScale="0"
        android:toXScale="1"
        android:fromYScale="0"
        android:toYScale="1"
        android:duration="1000"
        android:pivotX="50%"
        android:pivotY="50%">
    </scale>

</set>

技術博客:

Android Animation運行原理詳解:https://www.jianshu.com/p/fcd9c7e9937e

Android自定義View--Matrix Camera:http://www.gcssloop.com/customview/matrix-3d-camera

Android中的View動畫和屬性動畫:https://www.jianshu.com/p/b117c974deaf

Android 屬性動畫(Property Animation) 完全解析 (上):https://blog.csdn.net/lmj623565791/article/details/38067475

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章