天天看點

Android的動畫:ScaleAnimation,AlphaAnimation,RotateAnimation,TranslateAnimation,Code,DrawableAnimation

簡介

動畫有下面兩種情況
    同一個圖形通過視圖在界面上進行透明度,縮放,旋轉,平移的變化(View動畫)
    在界面的同一個位置上不斷切換顯示不同的圖檔(Drawable動畫)

動畫的分類
    View Animation
    Drawable Animation

Android中提供了兩種實作動畫的方式
    純編碼的方式
    Xml配置的方式      

View Animation

Animation公用的方法和屬性

setDuration(long durationMillis) : 設定持續時間(機關ms)
setStartOffset(long startOffset) : 設定開始的延遲的時間(機關ms)
setFillBefore(boolean fillBefore) : 設定最終是否固定在起始狀态
setFillAfter(boolean fillAfter) : 設定最終是否固定在最後的狀态
setAnimationListener(AnimationListener listener) : 設定動畫監聽

坐标類型:
    Animation.ABSOLUTE   :這個是絕對坐标,就是直接寫坐标值
    Animation.RELATIVE_TO_SELF    :這個是相對坐标,而且是相對自己的,以自己的左上頂點為參考點
    Animation.RELATIVE_TO_PARENT  "這個是相對父節點的左上頂點為參考點

啟動動畫 : view.startAnimation(animation);
結束動畫: view.clearAnimation()

動畫監聽器 : AnimationListener
  onAnimationStart(Animation animation) : 動畫開始的回調
  onAnimationEnd(Animation animation) : 動畫結束的回調
  onAnimationRepeat(Animation animation) : 動畫重複執行      

分類

單一動畫(Animation)
    縮放動畫(ScaleAnimation)
    透明度動畫(AlphaAnimation)
    旋轉動畫(RotateAnimation)
    平移動畫(TranslateAnimation)

複合動畫(AnimationSet)
    由多個單一動畫組合在一起的動畫

從下面的關系可以看出Animation和AnimationSet的關系就好像之前
View和Viewgroup的關系一樣      

ScaleAnimation

編碼方式
public ScaleAnimation(float fromX, float toX, float fromY, float toY,
        int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

fromX : 開始時X軸上的縮放比例   
toX : 結束時X軸上的縮放比例   
fromY :開始時Y軸上的縮放比例
toY :結束時Y軸上的縮放比例

pivotXType : X軸坐标的類型(計算x軸上的偏移量的方式)
pivotXVlaue : 中心點在X軸相對視圖左頂點在x軸上的偏移量
pivotYType :  Y軸坐标的類型(計算x軸上的偏移量的方式)
pivotYValue : 中心點相對視圖左頂點在y軸上的偏移量      
/*
   * 編碼實作: 縮放動畫 
   * ScaleAnimation
   *    //1. 建立動畫對象
   *    //2. 設定
   *    //3. 啟動動畫
   */
  public void startCodeScale(View v)
  {
    tv_animation_msg.setText("Code縮放動畫: 寬度從0.5到1.5, 高度從0.0到1.0, "
        + "縮放的圓心為頂部中心點,延遲1s開始,持續2s,最終還原");
    // 1. 建立動畫對象
    ScaleAnimation animation = new ScaleAnimation(0.5f, 1.5f, 0, 1,
        Animation.ABSOLUTE, iv_animation.getWidth() / 2,Animation.ABSOLUTE, 0);
    animation = new ScaleAnimation(0.5f, 1.5f, 0, 1,
        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0);
    // 2. 設定
    // 延遲1s開始
    animation.setStartOffset(1000);
    // 持續2s
    animation.setDuration(2000);
    // 最終還原
    animation.setFillBefore(true);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      
檔案方式
Animation.ABSOLUTE : 
    數值(預設以px為機關)   100
Animation.RELATIVE_TO_SELF : 
    百分數,如:50% (以目前視圖的寬度或高度其為基數來計算)   
Animation.RELATIVE_TO_PARENT : 
    百分數+p,如:50%p (以父視圖的寬度或高度其為基數來計算)
      
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:fromYScale="0"
    android:toXScale="1.5"
    android:toYScale="1" 
    android:startOffset="1000"
    android:duration="3000"
    android:pivotX="100%"
    android:pivotY="100%"
    android:fillAfter="true">

</scale>      
/*
   * xml實作: 縮放動畫 
   * <scale>
   */
  /*
   1. 定義動畫檔案
   2. 加載動畫檔案得到動畫對象
   3. 啟動動畫
   */
  public void startXmlScale(View v)
  {
    tv_animation_msg.setText("Xml縮放動畫: Xml縮放動畫: "
        + "寬度從0.0到1.5, 高度從0.0到1.0, 延遲1s開始,持續3s,圓心為右下角, 最終固定");

    // 1. 定義動畫檔案
    // 2. 加載動畫檔案得到動畫對象
    Animation animation = AnimationUtils.loadAnimation(this,R.anim.scale_test);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      

AlphaAnimation

編碼方式
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
            int pivotYType, float pivotYValue)

    fromDegrees : 開始時的角度
    toDegrees : 結束時的角度
    
    pivotXType : X軸坐标的類型
    pivotXVlaue : X軸坐标的值
    pivotYType :  Y軸坐标的類型
    pivotYValue : Y軸坐标的值      
/*
   * 編碼實作: 旋轉動畫 RotateAnimation
   */
  public void startCodeRotate(View v)
  {
    tv_animation_msg.setText("Code旋轉動畫: 以圖檔中心點為中心, 從負90度到正90度, 持續5s");
    // 1. 建立動畫對象
    RotateAnimation animation = new RotateAnimation(-90, 90,
        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
    // 2. 設定
    animation.setDuration(5000);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      
檔案方式
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90" 
    android:toDegrees="-90"
    android:duration="5000">
    
</rotate>      
/*
   * xml實作: 旋轉動畫 
   * <rotate>
   */
  public void startXmlRotate(View v)
  {
    tv_animation_msg.setText("Xml旋轉動畫: 以左頂點為坐标, 從正90度到負90度, 持續5s");
    // 1. 定義動畫檔案
    // 2. 加載動畫檔案得到動畫對象
    Animation animation = AnimationUtils.loadAnimation(this,R.anim.rotate_test);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      

RotateAnimation

編碼方式
/*
   * 編碼實作: 透明度動畫 
   * 完全透明 : 0
   * 完全不透明 : 1
   * AlphaAnimation
   */
  public void startCodeAlpha(View v)
  {
    tv_animation_msg.setText("Code透明度動畫: 從完全透明到完全不透明, 持續2s");
    // 1. 建立動畫對象
    AlphaAnimation animation = new AlphaAnimation(0, 1);
    // 2. 設定
    animation.setDuration(4000);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      
檔案方式
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1" 
    android:toAlpha="0"
    android:duration="4000">

</alpha>      
/*
   * xml實作: 透明度動畫 
   * <alpha>
   */
  public void startXmlAlpha(View v)
  {
    tv_animation_msg.setText("Xml透明度動畫: 從完全不透明到完全透明, 持續4s");
    // 1. 定義動畫檔案
    // 2. 加載動畫檔案得到動畫對象
    Animation animation = AnimationUtils.loadAnimation(this,
        R.anim.alpha_test);
    animation.setFillAfter(true);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      

TranslateAnimation

編碼方式
/*
   * 編碼實作: 平移動畫 TranslateAnimation
   */
  public void startCodeTranslate(View v)
  {
    tv_animation_msg.setText("Code移動動畫: 向右移動一個自己的寬度, 向下移動一個自己的高度, 持續2s");
    // 1. 建立動畫對象
    TranslateAnimation animation = new TranslateAnimation(
        Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1,
        Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1);
    // 2. 設定
    animation.setDuration(2000);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      
檔案方式
<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%p" 
    android:toXDelta="0"
    android:fromYDelta="0"
    android:toYDelta="0"
    android:duration="2000">
</translate>      
/*
   * xml實作: 平移動畫 
   * <translate>
   */
  public void startXmlTranslate(View v)
  {
    tv_animation_msg.setText("xml移動動畫: 從螢幕的右邊逐漸回到原來的位置, 持續2s"); 
    // ***此效果用于界面切換的動畫效果
    // 1. 定義動畫檔案
    // 2. 加載動畫檔案得到動畫對象
    Animation animation = AnimationUtils.loadAnimation(this,
        R.anim.translate_test);
    // 3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      

Code Animation

編碼方式
/*
   * 編碼實作: 複合動畫 AnimationSet
   */
  public void startCodeAnimationSet(View v)
  {
    tv_animation_msg.setText("Code複合動畫: 透明度從透明到不透明, 持續2s, "
        + "接着進行旋轉360度的動畫, 持續1s");
    // 1. 建立透明動畫并設定
    AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
    alphaAnimation.setDuration(2000);
    // 2. 建立旋轉動畫并設定
    RotateAnimation rotateAnimation = new RotateAnimation(0, 360,
        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
        0.5f);
    rotateAnimation.setDuration(1000);
    rotateAnimation.setStartOffset(2000);// 延遲
    // 3. 建立複合動畫對象
    AnimationSet animationSet = new AnimationSet(true);
    // 4. 添加兩個動畫
    animationSet.addAnimation(alphaAnimation);
    animationSet.addAnimation(rotateAnimation);
    // 5. 啟動複合動畫對象
    iv_animation.startAnimation(animationSet);
  }      
檔案方式
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <alpha
        android:duration="2000"
        android:fromAlpha="0"
        android:toAlpha="1" >
    </alpha>

    <rotate
        android:duration="2000"
        android:fromDegrees="0"
        android:startOffset="2000"
        android:toDegrees="360" />
</set>      
/*
   * xml實作: 複合動畫 
   * <set>
   */
  public void startXmlAnimationSet(View v) {
    tv_animation_msg.setText("Xml複合動畫: 透明度從透明到不透明, 持續2s, 接着進行旋轉360度的動畫, 持續2s");
    //1. 定義動畫檔案
    //2. 加載動畫檔案得到動畫對象
    Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_test);
    //3. 啟動動畫
    iv_animation.startAnimation(animation);
  }      

動畫監聽

在程式中可以對動畫的特定時刻進行監聽
    Animation.setAnimationListener(AnimationListener listener) : 設定動畫監聽

動畫監聽器 : AnimationListener
    onAnimationStart(Animation animation) : 動畫開始的回調
    onAnimationEnd(Animation animation) : 動畫結束的回調
    onAnimationRepeat(Animation animation) : 動畫重複執行      

Interpolator屬性

Interpolator 被用來修飾動畫效果,定義動畫的變化率,
 可以使存在的動畫效果accelerated(加速),decelerated(減速),repeated(重複)等。

    @android:anim/linear_interpolator  : 線性變化
    
    @android:anim/accelerate_interpolator  : 加速變化
    
    @android:anim/decelerate_interpolator  : 減速變化
    
    @android:anim/cycle_interpolator : 周期循環變化      

Drawable Animation

首先建立drawable檔案夾下面的xml檔案      
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" 
    android:oneshot="false">

    <item
        android:drawable="@drawable/nv1"
        android:duration="500"/>
    <item
        android:drawable="@drawable/nv2"
        android:duration="500"/>
    <item
        android:drawable="@drawable/nv3"
        android:duration="500"/>
    <item
        android:drawable="@drawable/nv4"
        android:duration="500">
    </item>

</animation-list>      
然後在圖檔視圖裡面引用這個檔案      
<ImageView
        android:id="@+id/iv_da_mm"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="160dp"
        android:background="@drawable/drawable_animation_test"/>      
然後還要得到背景動畫圖檔對象來進行啟動和停掉      
@Override
  public void onClick(View v)
  {
    if (v == btn_da_start)
    {
      if (animationDrawable == null)
      {
        // 得到背景動畫圖檔對象
        animationDrawable = (AnimationDrawable) iv_da_mm.getBackground();
        // 啟動
        animationDrawable.start();
      }

    } else if (v == btn_da_stop)
    {
      if (animationDrawable != null)
      {
        animationDrawable.stop();
        animationDrawable = null;
      }
    }
  }