Android 動畫

ValHewlett 8年前發布 | 4K 次閱讀 安卓開發 Android開發 移動開發

Android中動畫分為三種:

  • 逐幀動畫

  • 補間動畫

  • 屬性動畫

逐幀動畫

逐幀動畫類似于gif或是電影的原理,通過將一系列圖片連續播放來獲得動畫效果。它本質是一種Drawable,由ImageView播放。

定義逐幀動畫有兩種方式:

drawable文件夾下定義xml:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                android:oneshot="boolean">

    <item
        android:drawable="@..."
        android:duration="integer"/>
    <item .../>

</animation-list>

android:oneshot 指示是否重復播放

java代碼:

創建 AnimationDrawable 對象,使用 addFrame(Drawable frame, int duration) 向動畫添加幀。

AnimationDrawable默認是不播放的,調用 start() 、 stop() 來控制動畫的播放和停止。

補間動畫

補間動畫指定動畫開始和結束時的狀態(透明度、大小、位移、旋轉等),由系統根據指定的Interpolator(插值器)來生成過程幀,并實現動畫過程。

補間動畫有個很明顯的缺點, 動畫改變的只是顯示,并沒有改變事件響應的位置 。比方說我們通過補間動畫將Button移到了另一個位置,但是我們依然得點Button原來的位置才能觸發Button的點擊事件。

動畫的顯示會依賴于父控件的大小,若父控件太小,動畫可能會移出父控件邊緣,導致動畫不可見。

創建動畫的基本流程:

  1. 創建動畫實例

  2. 設置動畫持續時間、插值器等

  3. 調用view的 startAnimation() 方法并傳入動畫實例

  • 透明度動畫

    AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
    alphaAnimation.setDuration(1000);
    view.startAnimation(alphaAnimation)

    0代表完全透明,1為不透明。

  • 旋轉動畫

    RotateAnimation rotateAnimation = new RotateAnimation(0, 720, 75, 75); // 開始角度、結束角度、旋轉中心X坐標、旋轉中心Y坐標(此處X,Y是以View自身為參考系)
    RotateAnimation rotateAnimation = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 2f, Animation.RELATIVE_TO_SELF, 2f);// 開始角度、結束角度、X旋轉參考,X方向上與自身大小比值、Y旋轉參考,Y方向上與自身大小比值(參考系依然為View本身)

    旋轉動畫可指定旋轉中心的坐標與參考View寬高的比值, RELATIVE_TO_SELF 或 RELATIVE_TO_PARENT ,值得注意的是,X,Y的坐標始終是以 View自身為參考系

  • 位移動畫

    TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 300);// 起始X、結束X、起始Y、結束Y
    TranslateAnimation translateAnimation = new TranslateAnimation(
          Animation.RELATIVE_TO_PARENT, 0,
          Animation.RELATIVE_TO_SELF, 1,
          Animation.RELATIVE_TO_SELF, 0,
          Animation.RELATIVE_TO_SELF, 2);// 相對方式
  • 縮放動畫

    ScaleAnimation scaleAnimation = new ScaleAnimation(0.5f, 2, 0.5f, 2);// 數字表倍率
    ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1,
          Animation.RELATIVE_TO_SELF, 0.5f,
          Animation.RELATIVE_TO_SELF, 0.5f);// 指定縮放中心坐標
  • 動畫集合

    通過AnimationSet,可以組合各種動畫,使其同時播放

    AnimationSet animationSet = new AnimationSet(true);
    
    animationSet.addAnimation(alphaAnimation);
    animationSet.addAnimation(rotateAnimation);
    animationSet.addAnimation(translateAnimation);
    animationSet.addAnimation(scaleAnimation);
    
    animationSet.setInterpolator(new AccelerateInterpolator());
    animationSet.setDuration(1000);
    
    image.startAnimation(animationSet);
  • 監聽器

    有時候我們需要監聽動畫的開始或結束等來做進一步操作,這時候可以對動畫設置監聽器:

    animation.setAnimationListener(new Animation.AnimationListener() {
      @Override
      public void onAnimationStart(Animation animation) {
    
      }
    
      @Override
      public void onAnimationEnd(Animation animation) {
    
      }
    
      @Override
      public void onAnimationRepeat(Animation animation) {
    
      }
    });

屬性動畫

屬性動畫,顧名思義,是對針對屬性的動畫,通過持續地改變某個屬性來實現View的動畫效果。與補間動畫不同,屬性動畫真實地改變了View的屬性值。

  • ObjectAnimator

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "translationX", 300);
    objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    objectAnimator.setDuration(300);
    objectAnimator.start();

    要操作的屬性必須具有get和set方法。如果屬性沒有get、set方法,可以自定義一個包裝類:

    private static class WrapperView {
      private View mTarget;
    
      public WrapperView(View target) {
          this.mTarget = target;
      }
    
      public int getWidth() {
          return mTarget.getLayoutParams().width;
      }
    
      public void setWidth(int width) {
          mTarget.getLayoutParams().width = width;
          mTarget.requestLayout();
      }
    }
  • PropertyValuesHolder

    要同時針對多個屬性進行動畫時使用:

    PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat("translationX", 300);
    PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("scaleX", 1, 0.1f);
    PropertyValuesHolder propertyValuesHolder3 = PropertyValuesHolder.ofFloat("scaleY", 1, 0.1f);
    ObjectAnimator.ofPropertyValuesHolder(button, propertyValuesHolder1, propertyValuesHolder2, propertyValuesHolder3).setDuration(1000).start();
  • ValueAnimator

    ValueAnimator更像是一個數值發生器,使用時通過監聽數值的變換來自己完成動畫的實現:

    ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
    animator.setTarget(view);
    animator.setDuration(1000).start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
          Float value = (Float) animation.getAnimatedValue();
          // TODO use the value  
      }
    });
  • 動畫時間監聽

    一個完整動畫有四個過程:start、repeat、end、cancel。有兩種監聽器可以選:

    animator.addListener(new Animator.AnimatorListener() {
      @Override
      public void onAnimationStart(Animator animation) {
    
      }
    
      @Override
      public void onAnimationEnd(Animator animation) {
    
      }
    
      @Override
      public void onAnimationCancel(Animator animation) {
    
      }
    
      @Override
      public void onAnimationRepeat(Animator animation) {
    
      }
    });

    或:

    animator.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {
          super.onAnimationEnd(animation);
      }
    });

    AnimatorListenerAdapter可以按需要實現監聽start、repeat、end、cancel、pause、resume過程。

  • AnimatorSet

    AnimatorSet 不能能像PropertyValuesHolder那樣同時實現多個動畫,同時還能精準控制動畫的順序:

    ObjectAnimator animator1 = ObjectAnimator.ofFloat(button, "translationX", 300);
    ObjectAnimator animator2 = ObjectAnimator.ofFloat(button, "scaleX", 1, 0, 1);
    ObjectAnimator animator3 = ObjectAnimator.ofFloat(button, "scaleY", 1, 0, 1);
    AnimatorSet set = new AnimatorSet();
    set.setDuration(1000);
    set.playTogether(animator1, animator2, animator3);
    set.start();

    playTogether、playSequentially、play().with()、play().before()、play().after()等來控制動畫順序。

  • xml中使用屬性動畫

    animator文件夾下xml:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
      android:duration="1000"
      android:propertyName="scaleX"
      android:valueFrom="1.0"
      android:valueTo="2.0"
      android:valueType="floatType">
    </objectAnimator>

    java代碼中:

    Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scalex);
    animator.setTarget(view);
    animator.start();
  • view的animate方法

    button.animate().alpha(0).y(300).setDuration(300)
          .withStartAction(new Runnable() {
              @Override
              public void run() {
    
              }
          })
          .withEndAction(new Runnable() {
              @Override
              public void run() {
    
              }
          })
          .start();

 

布局動畫

布局動畫是作用在ViewGroup上當布局中View增加的動畫過渡效果。可在xml中添加 android:animateLayoutChanges="true" ,為布局添加默認動畫。

java中自定義動畫:

LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
sa.setDuration(1000);
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5f); // 第二個參數是延遲
lac.setOrder(LayoutAnimationController.ORDER_NORMAL); // 當延遲不為0時,可指定View顯示順序,還有隨機和反序
ll.setLayoutAnimation(lac);

 

來自:http://www.jianshu.com/p/e1591694ccbe

 

 本文由用戶 ValHewlett 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!