Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android動畫之二:View Animation

Android動畫之二:View Animation

編輯:關於Android編程

如上一篇博客《Android動畫之一:Drawable Animation》所說,android動畫主要分為三大部分,上一篇博客已經講解Drawable Animation的用法,即逐幀地顯示圖片,經常運用於動態顯示一個進度動畫,這是出現頻率最高的應用場景。接下來,我們這篇文章將循序漸進,介紹View Animation。

View Animation也是我們平時很多書籍所說的Tweened Animation(有人翻譯為補間動畫)。View Animation分為4大類:AlphaAnimation,RotateAnimation,ScaleAnimation,TranslateAnimation,分別對應透明度,旋轉,大小,位移四種變化。

View Animation的效果由四個因素決定:1)初始狀態;2)結束狀態;3)持續時間;4)Interpolator。所以要定義一個View Animation,你只要定義以上四個因素,中間的過程怎麼變化則有系統自動計算出來。其中前3個因素很容易理解,第四個因素Interpolator比較特別,這個單詞不知道怎麼翻譯比較適合,很多書籍的翻譯都很奇怪。Interpolator是決定動畫進行過程的速度變化。比如:你將一個按鈕從屏幕左側運動到屏幕右側。可以讓它一直加速前進,或者先減速然後減速,這就是Interpolator發揮的作用,具體使用方法下面會說,先從簡單的說起。

像Drawable Animation一樣,定義一個View Animation可以用代碼的方式,也可以用XML文件的方式。我們先來寫一個最簡單的例子,對一個helloworld字符串進行移動,旋轉,放大,變暗,分別用代碼實現和XML文件實現。先用代碼實現。

首先新建工程:ViewAnimationDemo,並新建一個布局文件:animationjavacode.xml,如下:

ViewAnimationDemo eslayoutanimationjavacode.xml

 

  
該XML布局文件對應的Activity如下:

 

ViewAnimationDemo/src/com/CSDN/viewanimationdemo/AnimCodeActivity.java

 

public class AnimCodeActivity extends Activity {

	private TextView translation;
	private TextView rotate;
	private TextView scale;
	private TextView alpha;
	
	private Button button;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.animationjavacode);
        
        translation = (TextView) findViewById(R.id.translation);
        rotate = (TextView) findViewById(R.id.rotate);
        scale = (TextView) findViewById(R.id.scale);
        alpha = (TextView) findViewById(R.id.alpha);
        button = (Button) findViewById(R.id.fire);
        
        button.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				// 1&2: 確定起始狀態,結束狀態
				TranslateAnimation tAnim = new TranslateAnimation(0, 400, 0, 0);//橫向位移400個單位
				RotateAnimation rAnima = new RotateAnimation(0, 70);//順時針旋轉70度
				ScaleAnimation sAnima = new ScaleAnimation(0, 5, 0, 5);//橫向放大5倍,縱向放大5倍
				AlphaAnimation aAnima = new AlphaAnimation(1.0f, 0.0f);//從全不透明變為全透明
				// 3: 確定持續時間
				tAnim.setDuration(2000);
				rAnima.setDuration(2000);
				sAnima.setDuration(2000);
				aAnima.setDuration(2000);

				// 4: 確定Interpolator
				tAnim.setInterpolator(new AccelerateDecelerateInterpolator());
				
				// 啟動動畫
				translation.startAnimation(tAnim);
				rotate.startAnimation(rAnima);
				scale.startAnimation(sAnima);
				alpha.startAnimation(aAnima);	
			}
		});
        
    }

}

從代碼中不難看到,首先確定了動畫的起始狀態和結束狀態,然後通過setDuration(2000)設置持續時間,如果這裡不設置持續時間,將默認為30mx,基本肉眼看不到。最後我們設置了一個Interpolator,此處設置效果是動畫先減速進行,然後減速。默認狀態時勻速進行。沒錯,Interpolator的基本用法就是這麼容易。以上代碼效果圖如下:

\

接下來講解怎麼用xml定義動畫,按照android官網的介紹,定義View Animation的xml文件格式如下:

 



    
    
    
    
    
        ...
    

該文件只能有一個根結點,可以是,,,,,而其中,結點可以包含子節點,即可以包含,,,,,以此類推。

 

以上需要講解的兩個標簽屬性是android:interpolator和android:shareInterpolator,前者代表你所使用的interpolator,可以是系統自帶,也可以是自定義。而後者代表,是否將該Interpolator共享給子節點。其它子標簽的屬性很容易理解,基本看屬性名字就能懂,除了其中兩個,android:pivotX和android:pivotY,我們知道,pivot的意思是軸心的意思,所以這兩個屬性定義的是此次動畫變化的軸心位置,默認是左上角,當我們把它們兩者都賦值為50%,則變化軸心在中心。

接下來寫一個具體的例子,如下,還是在剛才的項目中進行。一般我們把定義動畫的xml文件放在res/anim目錄下,首先我們新建一個anim文件夾,然後新建一個xml文件,如下:

ViewAnimationDemo/res/anim/myanim.xml

 


    
    
        
        
    


上述例子的效果圖如下:

\

上面代碼中,有 唯一一個根節點,它有兩個子節點,然後其中的子節點擁有兩個自己的子節點。講解一下上面一些沒見過的標簽屬性。

andoird:fillAfter:前面一個例子中,我們的動畫結束後helloworld又回到了原來狀態,通過設置fillAfter為true,則動畫將保持結束的狀態,但是,如前一篇博客《Android動畫之一:Drawable Animation》所說,View Animation的動畫效果是繪制出來的,並非該組件真正移動了,這個問題我們後續會繼續探討。現在只需要知道將fillAfter設置為true之後,動畫將保持結束狀態,這大多應用於設計連續發生的動畫。

startOffset:該屬性定義動畫推遲多久開始,通過這個屬性的設置,我們可以設計一些前後按序發生的動畫,當然,除了最後一個發生的動畫,其他動畫得設置fillAfter為true.

interpolator:這裡我們使用了系統自帶的interpolator

接下來我們定義一個布局文件,該布局文件只有一張圖片,一個按鈕,通過點擊按鈕觸發圖片進行動畫,該布局文件比較簡單,這裡不列出。如何在該布局文件對應的activity代碼中啟動動畫呢,代碼如下:

ViewAnimationDemo/src/com/CSDN/viewanimationdemo/AnimaXmlActivity.java

 

public class AnimaXmlActivity extends Activity {

	private Button btn;
	private ImageView img;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_anima_xml);
		btn = (Button)findViewById(R.id.xml_btn);
		img = (ImageView)findViewById(R.id.xmlAnimImg);
		
		btn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Animation anim = AnimationUtils.loadAnimation(AnimaXmlActivity.this, R.anim.myanim);
				img.startAnimation(anim);
			}
		});
	}
}

以上代碼很容易理解,我們一般使用AnimationUtils讀取定義在xml文件中的動畫。

 

到此為止,關於View Animation的基礎知識基本已經覆蓋了,接下來寫一個具體實踐的例子,實現經常見到的側滑功能,如網易新聞這種:

\

 

這個側滑的效果實現並不難,很多人運用了AsyncTask線程,但是結果你會發現有時會發生明顯的卡頓,但是如果使用動畫效果將會平滑很多。我們接下來實現這樣的功能:

首先新建一個項目:SwipeWithAnim。並新建一個布局文件activity_main.xml,如下

SwipeWithAnim/res/layout/activity_main.xml

 

<framelayout android:layout_height="match_parent" android:layout_width="match_parent" tools:context=".MainActivity" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">

    

    

        

        
    

</framelayout>

屏幕顯示內容content,左側隱去菜單menu,知識將20dp的透明部分放在屏幕左側,用於觸發onTouch事件。該xml文件對應的activity代碼如下:

 

SwipeWithAnim/src/com/CSDN/swipewithanim/MainActivity.java

 

 

public class MainActivity extends Activity {

	private View menu;
	private final static int SHOW_MENU = 1;
	private final static int HIDE_MENU = -1;
	private int swipe_tag = SHOW_MENU;
	private int max_menu_margin = 0;
	private int min_menu_margin;
	private float beginX;
	private float latestX;
	private float diffX;
	private float latestMargin;

	private FrameLayout.LayoutParams lp;

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onCreate(android.os.Bundle)
	 */
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_main);

		menu = findViewById(R.id.menu);
		lp = (FrameLayout.LayoutParams) menu.getLayoutParams();
		min_menu_margin = lp.leftMargin;

		menu.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				int action = MotionEventCompat.getActionMasked(event);
				switch (action) {
				case MotionEvent.ACTION_DOWN:
					beginX = event.getX();
					break;
				case MotionEvent.ACTION_MOVE:
					latestX = event.getX();
					diffX = latestX - beginX;
					swipe_tag = diffX > 0 ? SHOW_MENU : HIDE_MENU;
					latestMargin = lp.leftMargin + diffX;

					if (latestMargin > min_menu_margin
							&& latestMargin < max_menu_margin) {
						lp.leftMargin = (int) (latestMargin);
						menu.setLayoutParams(lp);
					}

					break;
				case MotionEvent.ACTION_UP:
					TranslateAnimation tAnim;
					if (swipe_tag == SHOW_MENU) {
						tAnim = new TranslateAnimation(0, max_menu_margin
								- latestMargin, 0, 0);
						tAnim.setInterpolator(new DecelerateInterpolator());
						tAnim.setDuration(800);
						menu.startAnimation(tAnim);
					} else {
						tAnim = new TranslateAnimation(0, min_menu_margin
								- latestMargin, 0, 0);
						tAnim.setDuration(800);
						menu.startAnimation(tAnim);
					}
					//在動畫結束的時刻,移動menu的位置,使menu真正移動。
					tAnim.setAnimationListener(new AnimationListener() {

						@Override
						public void onAnimationStart(Animation animation) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationRepeat(Animation animation) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onAnimationEnd(Animation animation) {
							// TODO Auto-generated method stub
							if (swipe_tag == SHOW_MENU) {
								lp.leftMargin = max_menu_margin;
								menu.setLayoutParams(lp);
							} else {
								lp.leftMargin = min_menu_margin;
								menu.setLayoutParams(lp);
							}
							menu.clearAnimation();
						}
					});

					break;
				}
				return true;
			}
		});

	}

}

如上代碼,監聽menu的onTouch事件,然後根據移動距離移動menu,當手指拿起來時,啟動動畫,使移動繼續進行到結束。我們上面提到,View Animation只是繪制出來的效果,發生動畫的組件並非真正移動了,那麼此處為了解決這個問題,我們監聽了AnimationListener,在動畫結束時,將menu的位置移動到動畫結束的位置,這樣就成功移動了menu。效果圖如下,由於截圖軟件關系,看起來會卡頓,在真機上測試則完全平滑。

 

\

 

最後附上這篇博客前後的兩份源碼:

 

ViewAnimationDemo

SwipeWithAnim

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved