Android動畫使用之補間動畫

1. 前言

動畫在安卓中,使用是很是常見的,好比網絡請求時的loading,就是經過旋轉實現的。 在安卓中,動畫分爲兩大類, 分別是視圖動畫和屬性動畫。視圖動畫又分爲幀動畫和補間動畫。這篇文章主要講補間動畫的使用。三種動畫的使用文章地址以下:java

  1. 幀動畫
  2. 補間動畫
  3. 屬性動畫

2. 介紹

補間動畫指的是, 設置好動畫的開始屬性 和 結束屬性。 系統會在咱們設置的動畫時間內, 從開始時屬性過渡到結束時候的屬性。舉個例子,一個控件向右平移100像素,其實改變的屬性就是控件x軸的座標。系統提供了四種補間動畫,分別爲:android

  • 平移
  • 縮放
  • 旋轉
  • 透明度

3. 使用
3.1 平移動畫
  1. 在res/anim 目錄下新建動畫描述文件translate.xml,內容以下:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"


    android:duration="5000"
    android:startOffset="1000"
    android:fillBefore="true"
    android:fillAfter="false"
    android:fillEnabled="true"
    android:repeatMode="restart"
    android:repeatCount="3"


    android:fromXDelta="0"
    android:toXDelta="500"

    android:fromYDelta="0"
    android:toYDelta="500"
    >

</translate>
複製代碼

解釋:
第一部分是動畫的公共屬性,也就是其餘三種動畫也有這些屬性:git

  • duration:動畫時間,單位毫秒
  • startOffset:動畫延遲執行時間
  • fillBefore: 動畫播放完後,視圖是否會停留在動畫開始的狀態,默認爲true
  • fillAfter: 動畫播放完後,視圖是否會停留在動畫結束的狀態,優先於fillBefore值,默認爲false
  • fillEnable: 是否應用fillBefore值,對fillAfter值無影響,默認爲true
  • restart:選擇重複播放動畫模式,restart表明正序重放,reverse表明倒序回放,默認爲restart|
  • repeatCount:重放次數(因此動畫的播放次數=重放次數+1),爲infinite時無限重複 下面的是 平移動畫的特有屬性
  • fromXDelta:視圖在水平方向x 移動的起始值
  • toXDelta:視圖在水平方向x 移動的結束值
  • fromYDelta:視圖在豎直方向y 移動的起始值
  • toYdelta: 視圖在豎直方向y 移動的結束值
  1. 在Java代碼中加載動畫文件並播放
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
    iv.startAnimation(animation);
    複製代碼

至此動畫就已經定義完成並能夠播放了。 第一步中的xml方式也能夠經過java代碼來實現,代碼方式以下:github

Animation translateAnimation = new TranslateAnimation(0,500,0,500);
mation

translateAnimation.setDuration(3000);
// 固定屬性的設置都是在其屬性前加「set」,如setDuration()
iv.startAnimation(translateAnimation);
複製代碼

解釋:
bash

  • new TranslateAnimation():這是平移動畫的構造函數,傳入xml中平移動畫的那幾個特有屬性。
  • setDuration:經過setXX()方法設置上面xml中的動畫公共屬性
3.2 縮放動畫
  1. 在res/anim 目錄下新建動畫描述文件scale.xml,內容以下:\
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="3000"
    android:repeatCount="2"
    android:fillBefore="true"
    android:repeatMode="restart"

    android:fromXScale="0"
    android:toXScale="2"
    android:fromYScale="0"
    android:toYScale="2"
    android:pivotX="50%"
    android:pivotY="50%"
    >
</scale>
複製代碼

解釋:
網絡

  • fromXScale: 水平方向的起始縮放倍數
  • toXScale: 水平方向的結束縮放倍數
  • fromYScale: 垂直方向起始縮放倍數
  • toYScale: 垂直方向結束縮放倍數
  • pivotX:縮放中心點的x座標
  • pivotY: 縮放中心點的y座標
  1. 在Java代碼中加載動畫文件並播放
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
iv.startAnimation(animation);
複製代碼
3.3 旋轉動畫
  1. 在res/anim 目錄下新建動畫描述文件rotate.xml,內容以下:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:repeatCount="2"
    android:repeatMode="restart"
    android:fillBefore="true"

    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    >

</rotate>
複製代碼

解釋:
dom

  • fromDegrees:旋轉起始角度
  • toDegrees:旋轉結束角度
  • pivotX:旋轉中心點x軸座標
  • pivotY: 旋轉中心點y軸座標
  1. 在Java代碼中加載動畫文件並播放
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);
        iv.startAnimation(animation);
複製代碼
3.4 透明動畫
  1. 在res/anim 目錄下新建動畫描述文件alpha.xml,內容以下:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"
    android:startOffset="500"
    android:fillBefore="true"

    android:fromAlpha="1.0"
    android:toAlpha="0.0"
    >
</alpha>
複製代碼

解釋:
ide

  • fromAlpha:透明度起始值
  • toAlpha: 透明度結束值
  1. 在Java代碼中加載動畫文件並播放
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
        iv.startAnimation(animation);
複製代碼
3.5 組合動畫
  1. 在res/anim 目錄下新建動畫描述文件combination.xml,內容以下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"

    android:duration="3000"
    android:fillBefore="true"
    android:repeatCount="0"
    android:repeatMode="restart"
    android:shareInterpolator="true"
    >

    <translate
        android:fromXDelta="0"
        android:toXDelta="250"
        android:fromYDelta="0"
        android:toYDelta="-250"
        android:duration="3000"
        >
    </translate>


    <rotate
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="3000"
        android:fromDegrees="0"
        android:toDegrees="30"
        >
    </rotate>


    <!--<alpha-->
        <!--android:duration="3000"-->
        <!--android:fromAlpha="1.0"-->
        <!--android:toAlpha="0.5"-->
        <!--/>-->


</set>
複製代碼

解釋:
函數

  • set:組合動畫的根節點
  • shareInterpolator:表示組合動畫中的動畫是否和集合共享同一個差值器,若是集合不指定插值器,那麼子動畫須要單獨設置

特別注意:
佈局

  • 組合動畫播放時是所有動畫同時開始,若是想不一樣動畫不一樣時間開始就要使用android:startOffset屬性來延遲單個動畫播放時間。
  • 在組合動畫裏scale縮放動畫設置的repeatCount(重複播放)和fillBefore(播放完後,視圖是否會停留在動畫開始的狀態)是無效的。因此若是須要重複播放或者回到原位的話須要在set標籤裏設置。
  1. 在Java代碼中加載動畫文件並播放
Animation animation = AnimationUtils.loadAnimation(this, R.anim.combination);
        iv.startAnimation(animation);
複製代碼

4. 實例

image

  1. xml佈局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_water"
        android:layout_width="35dp"
        android:layout_height="35dp"
        android:src="@mipmap/water"
        android:layout_centerInParent="true"
        android:layout_above="@id/iv_shumiao"
        android:visibility="gone"
        />

    <ImageView
        android:id="@+id/iv_shumiao"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/shumiao"
        android:layout_centerInParent="true"
        />

    <ImageView
        android:id="@+id/iv_shuihu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/shuihu"
        android:layout_below="@id/iv_shumiao"
        />

</RelativeLayout>

複製代碼
  1. java編寫組合動畫
package com.domain.study.animation.tween;

import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;

import com.domain.study.animation.R;
import com.domain.study.animation.base.BaseActivity;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class TweenCombinationActivity extends BaseActivity {

    @BindView(R.id.iv_shumiao)
    ImageView ivShumiao;
    @BindView(R.id.iv_shuihu)
    ImageView ivShuihu;
    @BindView(R.id.iv_water)
    ImageView ivWater;

    int shuiHuX = 0;
    int shuiHuY = 0;

    int shuMiaoX = 0;
    int shuMiaoY = 0;

    int shuMiaoWidth = 0;
    int shuMiaoHeight = 0;

    int shuiHuWidth = 0;
    int shuiHuHeight = 0;

    int waterHeight = 0;

    @Override
    protected int setLayoutId() {
        return R.layout.activity_combination;
    }

    @Override
    protected void initView() {
        ivShuihu.post(new Runnable() {
            @Override
            public void run() {
                int[] location = new int[2];
                ivShuihu.getLocationOnScreen(location);
                shuiHuX = location[0]; // view距離 屏幕左邊的距離(即x軸方向)
                shuiHuY = location[1]; // view距離 屏幕頂邊的距離(即y軸方向)
                shuiHuWidth = ivShuihu.getWidth();
                shuiHuHeight = ivShuihu.getHeight();
            }
        });
        ivShumiao.post(new Runnable() {
            @Override
            public void run() {
                int[] location = new int[2];
                ivShumiao.getLocationOnScreen(location);
                shuMiaoX = location[0]; // view距離 屏幕左邊的距離(即x軸方向)
                shuMiaoY = location[1]; // view距離 屏幕頂邊的距離(即y軸方向)

                shuMiaoWidth=ivShumiao.getWidth(); // 獲取寬度
                shuMiaoHeight =ivShumiao.getHeight(); // 獲取高度
            }
        });

        ivWater.post(new Runnable() {
            @Override
            public void run() {
                waterHeight = ivWater.getHeight();
            }
        });



    }


    @OnClick(R.id.iv_shuihu)
    public void onViewClicked() {
        start();
    }

    private void start(){

        AnimationSet setAnimation = new AnimationSet(true);

// 子動畫1:旋轉動畫
        Animation rotate = new RotateAnimation(0,10,0.5f,0.5f);
        rotate.setDuration(1000);
        rotate.setStartOffset(3000);

// 子動畫2:平移動畫
        Animation translate = new TranslateAnimation(
                0,
                shuMiaoX-shuiHuWidth,
                0
                ,-(shuiHuHeight+shuMiaoHeight+waterHeight+100));
        translate.setDuration(3000);


//等待水滴落下動畫
        Animation wait = new TranslateAnimation(
                0,
                0,
                0
                ,0);
        wait.setStartOffset(4000);
        wait.setDuration(2000);




// 將建立的子動畫添加到組合動畫裏
        setAnimation.addAnimation(translate);
        setAnimation.addAnimation(rotate);
        setAnimation.addAnimation(wait);

        ivShuihu.startAnimation(setAnimation);


        rotate.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                ivWater.setVisibility(View.VISIBLE);
                startWaterAnimation();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

    }

    private void startWaterAnimation(){

        AnimationSet animationSet = new AnimationSet(true);

        TranslateAnimation translateAnimation = new TranslateAnimation(0,0,0,50);
        translateAnimation.setDuration(2000);

        AlphaAnimation alphaAnimation = new AlphaAnimation(1,0);
        alphaAnimation.setDuration(2000);

        animationSet.addAnimation(translateAnimation);
        animationSet.addAnimation(alphaAnimation);
        ivWater.startAnimation(animationSet);

        animationSet.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                ivWater.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

    }

}

複製代碼
5.總結
  • 補間動畫系統提供了四種,分別是:平移、縮放、旋轉、透明度。
  • 動畫能夠經過xml文件來描述,也能夠經過java代碼來實現。
  • 補間動畫只能做用在view上。
  • 補間動畫其實沒有改變view的真實屬性,好比動畫後看到的view,是沒辦法點擊的。
  • 能夠經過組合動畫,把四種動畫結合使用。
  • 組合動畫啓動時,全部的子動畫是同時啓動的,若是要有前後順序,能夠經過子動畫的延時執行來實現。

6. 完整demo地址

7. 參考文章

8. 歷史文章目錄
相關文章
相關標籤/搜索