編輯:關於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); } }); } }
到此為止,關於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>
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; } }); } }
最後附上這篇博客前後的兩份源碼:
ViewAnimationDemo
SwipeWithAnim
AsyncTask的隱蔽陷阱先來看一個實例這個例子很簡單,展示了AsyncTask的一種極端用法,挺怪的。復制代碼 代碼如下:public class AsyncTask
經常玩兒App的小伙伴都知道,APP上面有很多按鈕都是圓角的,圓形給人感覺飽滿,富有張力,不知道設計圓角按鈕的小伙伴是不是和小編有著相同的想法`(*∩_∩
Activity棧主要用於管理Activity的切換。當使用Intent跳轉至某個目標Activity,需要根據目標Activity的加載模式來加載。Activity一共
android大家都有很多需要用戶上傳頭像的需求,有的是選方形,有的是圓角矩形,有的是圓形。首先我們要做一個處理圖片的自定義控件,把傳入的圖片,經過用戶選擇區域,處理成一