1. 程式人生 > >安卓的屬性動畫基本用法(一)

安卓的屬性動畫基本用法(一)

    休假歸來,十幾天的婚假過得真快,時間不管對誰都是不夠用的,我們能做的只能是珍惜時間。

    上篇文章講解了補間動畫,這次我們來看看屬性動畫,先給大家看看兩張效果圖,大家看看其中的不同:

    第一張(補間動畫):

   

   第二張(屬性動畫):

  

  模擬器錄製的第二張比較卡,但是大致的效果是能看出來的,大家也能一目瞭然的看出兩張圖的區別吧,那就是點選“飄逸的我”按鈕的點選事件的不同,其實這就是補間動畫和屬性動畫的本質的區別。補間動畫雖能對控制元件做動畫,但並沒有改變控制元件內部的屬性值。而Property Animator則是恰恰相反,Property Animator是通過改變控制元件內部的屬性值來達到動畫效果的。

 下面看下程式碼:

public class MainActivity extends Activity implements OnClickListener {

	private Button btn_move;
	private Button btn_start;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
		setListener();
	}


	private void initView() {
		btn_start = (Button) findViewById(R.id.btn_start);
		btn_move = (Button) findViewById(R.id.btn_move);
		
	}

	private void setListener() {
		btn_start.setOnClickListener(this);
		btn_move.setOnClickListener(this);
	}


	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_start:
//			viewAnimation(btn_move);        //補間動畫
	        propertyAnimation(btn_move);    //屬性動畫
			break;
		case R.id.btn_move:
			Toast.makeText(this, "點我幹嘛", 0).show();
			break;
		default:
			break;
		}
	}


	private void propertyAnimation(final View view) {
	    ValueAnimator animator = ValueAnimator.ofInt(0,200);  
	    animator.setDuration(1500);  
	      
	    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
	        @Override  
	        public void onAnimationUpdate(ValueAnimator animation) {  
	            int curValue = (int)animation.getAnimatedValue();  
	            view.layout(dp2px(MainActivity.this, 100), dp2px(MainActivity.this, 100)+curValue, dp2px(MainActivity.this, 100)+view.getWidth(), curValue+view.getHeight()+dp2px(MainActivity.this, 100));
	        }  
	        
	    });
	    //屬性動畫的相關監聽
	    animator.addListener(new AnimatorListener() {
			
			@Override
			public void onAnimationStart(Animator animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationRepeat(Animator animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationEnd(Animator animation) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onAnimationCancel(Animator animation) {
				// TODO Auto-generated method stub
				
			}
		});
	    animator.start();  
	}


	private void viewAnimation(View view) {
		TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, 200);
		translateAnimation.setFillAfter(true);
		translateAnimation.setDuration(1500);
		view.startAnimation(translateAnimation);
	}
	/**
	 * 根據手機的解析度從 dp 的單位 轉成為 px(畫素)
	 */
	public  int dp2px(Context context, int dpValue) {
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dpValue * scale + 0.5f);
	}
}
   以上是MainActivity的所有程式碼,這裡要提的是上篇介紹的補間動畫都是用xml的形式來實現的,而這邊直接程式碼實現,所以像補間動畫的實現大家自己看著用,習慣用程式碼實現的就用程式碼實現,習慣用xml實現的就用xml實現。其實程式碼實現也簡單:
	private void viewAnimation(View view) {
		TranslateAnimation translateAnimation = new TranslateAnimation(0, 0, 0, 200);
		translateAnimation.setFillAfter(true);
		translateAnimation.setDuration(1500);
		view.startAnimation(translateAnimation);
	}
   好,下面就來分析屬性動畫怎麼用的吧!

  屬性動畫Property Animator包括ValueAnimator和ObjectAnimator;而我們這篇用到的是ValueAnimator。

  先看ValueAnimator的相關程式碼:

	    ValueAnimator animator = ValueAnimator.ofInt(0,200);  
	    animator.setDuration(1500);  
	      
	    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
	        @Override  
	        public void onAnimationUpdate(ValueAnimator animation) {  
	            int curValue = (int)animation.getAnimatedValue();  
	            view.layout(dp2px(MainActivity.this, 100), dp2px(MainActivity.this, 100)+curValue, dp2px(MainActivity.this, 100)+view.getWidth(), curValue+view.getHeight()+dp2px(MainActivity.this, 100));
	        }  
	        
	    });
	    animator.start(); 
java的核心思想面向物件,我們要用屬性動畫肯定要拿到屬性動畫的相關例項,那麼第一步就是建立屬性動畫的相關例項:

ValueAnimator animator = ValueAnimator.ofInt(0,200); 
大家可能比較迷惑ofInt(0,200)是啥意思?不用怕,不懂我們就查查原始碼,看看原始碼怎麼說的:

  /**
     * Constructs and returns a ValueAnimator that animates between int values. A single
     * value implies that that value is the one being animated to. However, this is not typically
     * useful in a ValueAnimator object because there is no way for the object to determine the
     * starting value for the animation (unlike ObjectAnimator, which can derive that value
     * from the target object and property being animated). Therefore, there should typically
     * be two or more values.
     *
     * @param values A set of values that the animation will animate between over time.
     * @return A ValueAnimator object that is set up to animate between the given values.
     */
    public static ValueAnimator ofInt(int... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setIntValues(values);
        return anim;
    }

    /**
     * Constructs and returns a ValueAnimator that animates between color values. A single
     * value implies that that value is the one being animated to. However, this is not typically
     * useful in a ValueAnimator object because there is no way for the object to determine the
     * starting value for the animation (unlike ObjectAnimator, which can derive that value
     * from the target object and property being animated). Therefore, there should typically
     * be two or more values.
     *
     * @param values A set of values that the animation will animate between over time.
     * @return A ValueAnimator object that is set up to animate between the given values.
     */
    public static ValueAnimator ofArgb(int... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setIntValues(values);
        anim.setEvaluator(ArgbEvaluator.getInstance());
        return anim;
    }

    /**
     * Constructs and returns a ValueAnimator that animates between float values. A single
     * value implies that that value is the one being animated to. However, this is not typically
     * useful in a ValueAnimator object because there is no way for the object to determine the
     * starting value for the animation (unlike ObjectAnimator, which can derive that value
     * from the target object and property being animated). Therefore, there should typically
     * be two or more values.
     *
     * @param values A set of values that the animation will animate between over time.
     * @return A ValueAnimator object that is set up to animate between the given values.
     */
    public static ValueAnimator ofFloat(float... values) {
        ValueAnimator anim = new ValueAnimator();
        anim.setFloatValues(values);
        return anim;
    }
    上面的註釋的英文比較的簡單,大致的意思就是引數裡面值至少要有兩個,一個開始值一個結束值,動畫會在這點規定的點之間進行變化。當然你也可以設定一系列的值,那麼我也給大家展示一下設定一系列值的效果:

  這裡我把程式碼改為: ValueAnimator animator = ValueAnimator.ofInt(0,200,-60,300); 
 

其實就是動畫線性點的變化;大家有沒有注意到我在給大家展示原始碼的時候還展示了兩個方法ofArgb(int... values)和ofFloat(float... values),這兩個方法是什麼意思呢?先不要急,一步步往下看,我們第一步建立了ValueAnimator的例項。

第二部: animator.setDuration(1500);  這個就不解釋了,你懂得!

第三部:   animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {  
                int curValue = (int)animation.getAnimatedValue();  
                view.layout(dp2px(MainActivity.this, 100), dp2px(MainActivity.this, 100)+curValue, dp2px(MainActivity.this, 100)+view.getWidth(), curValue+view.getHeight()+dp2px(MainActivity.this, 100));
            }  
            
        });

這是最關鍵的一步,動畫時刻更新的監聽器,其中在onAnimationUpdate的重寫方法中有一個   int curValue = (int)animation.getAnimatedValue();可能大家不知道這個得到的int值是什麼,無妨看下日誌:

   我只是截取了一部分,其實就是我們設定的ofInt(0,200)值的變化,  int curValue = (int)animation.getAnimatedValue();  其實這邊有一個強制的轉換直接強轉為int了,為什麼?因為我們在建立例項的時候用的是ofInt(),如果你用的是ofFloat()那這邊只能強制轉換為float。那可能大家有想問什麼時候用ofInt什麼時候用ofFloat呢?其實很簡單具體的就要看你的屬性動畫是用來幹什麼的,我這邊是位置的改變用到的是:

view.layout(dp2px(MainActivity.this, 100), dp2px(MainActivity.this, 100)+curValue, dp2px(MainActivity.this, 100)+view.getWidth(), curValue+view.getHeight()+dp2px(MainActivity.this, 100));
view.layout(int l, int t, int r, int b),這個方法裡面用到的是int值那麼我就用ofInt,如果你的屬性動畫想來改變透明度那就用ofFloat,如果你想改變色值就要用ofArgb了,所以一切就看你想要什麼。當然屬性動畫也有著自己基本的方法,比如設定插值器,設定重複模式,設定重複次數,這些基本的東西不管什麼動畫都是有的,我也不具體的說明了。
  animator.setInterpolator(new BounceInterpolator());
	    animator.setRepeatCount(1);
	    animator.setRepeatMode(ValueAnimator.RESTART);
   好了,屬性動畫的ValueAnimator的簡單用法就介紹到這了,關於更深層次的東西大家可以自己慢慢去研究。

  最後送給大家一句話,窮則變,變則通,窮則變通,海闊天空!