Android爲我們提供了2中動畫
一: Tween Animation 漸變動畫 通過對特定對象做圖像的變換,例如: 平移, 縮放,旋轉, 淡入淡出 等。
二: Frame Animation 幀動畫 創建一個淡入阿瓦不了可以按照指定的時間間隔一個一個顯示。順序播放
下面我們就詳細介紹一下這兩中動畫:
首先我們介紹 漸變動畫:
1. Tween Animation
1. 漸變動畫有四種樣式:
alpha: 漸變透明度
scale: 縮放尺寸伸縮動畫
translate: 移動動畫效果
rotate : 旋轉動畫
2.使用方式:
2.1 可以通過xml資源文件設置, 然後通過AnimationUtils的LoadAnimation方法加載
舉例:
alpha: 漸變透明度
<alpha android:interpolator= “@android:anim/accelerate_decelerate_interpolator”
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="3000"
></alpha>
<!--
interpolator:指定一個動畫的插入器,用來控制動畫的速度變化
fromAlpha:動畫起始時透明度
0.0表示完全透明
1.0表示完全不透明
以上值取0.0-1.0之間的float數據類型的數字
toAlpha:動畫結束時透明度
duration:持續時間 -->
scale: 縮放尺寸伸縮動畫
<scale
android:interpolator= “@android:anim/accelerate_decelerate_interpolator”
android:fromXScale=”0.0″
android:toXScale=”1.4″
android:fromYScale=”0.0″
android:toYScale=”1.4″
android:pivotX=”50%”
android:pivotY=”50%”
android:fillAfter=”false”
android:startOffset=“700”
android:duration=”700″
android:repeatCount=”10″ />
<!--
fromXScale[float]:爲動畫起始時,X座標上的伸縮尺寸,0.0表示收縮到沒有
fromYScale[float]:爲動畫起始時,Y座標上的伸縮尺寸,0.0表示收縮到沒有
1.0表示正常無伸縮
值小於1.0表示收縮
值大於1.0表示放大
toXScale[float]:爲動畫結束時,X座標上的伸縮尺寸
toYScale[float]:爲動畫結束時,X座標上的伸縮尺寸
pivotX[float]:爲動畫相對於物件的X座標的開始位置
pivotY[float]:爲動畫相對於物件的X、Y座標的開始位置
50,50%,50%p。這三種寫法就分別代表了ABSOLUTE,RELATIVE_TO_SELF和RELATIVE_TO_PARENT。
屬性值說明:從0%-100%中取值,50%爲物件的X或Y方向座標上的中點位置
fillAfter[boolean]:當設置爲true ,該動畫轉化在動畫結束後被應用
startOffset[long]:動畫之間的時間間隔,從上次動畫停多少時間開始執行下個動畫
repeatCount[int]:動畫的重複次數 -->
<translate
android:interpolator=”@android:anim/accelerate_decelerate_interpolator”
android:fromXDelta=”30″
android:toXDelta=”-80″
android:fromYDelta=”30″
android:toYDelta=”300″
android:duration=”2000″ />
t;!--
fromXDelta:爲動畫起始時 X座標上的位置
toXDelta: 爲動畫結束時 X座標上的位置
fromYDelta: 爲動畫起始時 Y座標上的位置
toYDelta:爲動畫結束時 Y座標上的位置 -->
rotate : 旋轉動畫
<rotate
android:interpolator=”@android:anim/accelerate_decelerate_interpolator”
android:fromDegrees=”0″
android:toDegrees=”+350″
android:pivotX=”50%”
android:pivotY=”50%”
android:duration=”3000″ />
t;!--
fromDegrees:動畫起始時物件的角度
toDegrees:動畫結束時物件旋轉的角度 可以大於360度
當角度爲負數——表示逆時針旋轉
當角度爲正數——表示順時針旋轉
(負數from——to正數:順時針旋轉)
(負數from——to負數:逆時針旋轉)
(正數from——to正數:順時針旋轉)
(正數from——to負數:逆時針旋轉)
pivotX;:爲動畫相對於物件的X、Y座標的開始位置
pivotY: 爲動畫相對於物件的X、Y座標的開始位置
50%爲物件的X或Y方向座標上的中點位置 -->
2.2 使用 Anmation的相關子類構造函數來初始化animation對象。
在android的sdk中提供了想要的類,animation類派生出了 aplhaAnimation ScaleAnimation TranslateAnimation RotateAnimation 分別實現了平移,旋轉,漸變,尺寸,和透明度等動畫
舉例:
//在代碼中定義 動畫實例對象
private Animation myAnimation_Alpha;
private Animation myAnimation_Scale;
private Animation myAnimation_Translate;
private Animation myAnimation_Rotate;
//根據各自的構造方法來初始化一個實例對象
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);
myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
myAnimation_Translate = new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f);
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
1. AlphaAnimationAlphaAnimation類對象定義
1. private AlphaAnimation myAnimation_Alpha;
AlphaAnimation類對象構造
AlphaAnimation(float fromAlpha, float toAlpha)
//第一個參數fromAlpha爲 動畫開始時候透明度
//第二個參數toAlpha爲 動畫結束時候透明度
myAnimation_Alpha = new AlphaAnimation(0.1f, 1.0f);
//說明:
// 0.0表示完全透明
// 1.0表示完全不透明
設置動畫持續時間
myAnimation_Alpha.setDuration(5000);
//設置時間持續時間爲 5000毫秒
2. ScaleAnimation
ScaleAnimation類對象定義
private ScaleAnimation myAnimation_Scale;
ScaleAnimation類對象構造
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座標上的伸縮尺寸
/*說明:
以上四種屬性值
0.0表示收縮到沒有
1.0表示正常無伸縮
值小於1.0表示收縮
值大於1.0表示放大
*/
//第五個參數pivotXType爲動畫在X軸相對於物件位置類型
//第六個參數pivotXValue爲動畫相對於物件的X座標的開始位置
//第七個參數pivotXType爲動畫在Y軸相對於物件位置類型
//第八個參數pivotYValue爲動畫相對於物件的Y座標的開始位置
myAnimation_Scale = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
設置動畫持續時間
myAnimation_Scale.setDuration(700);
//設置時間持續時間爲 700毫秒
3. TranslateAnimationranslateAnimation類對象定義
private TranslateAnimation myAnimation_Translate;
TranslateAnimation類對象構造
TranslateAnimation(float fromXDelta, float toXDelta,
float fromYDelta, float toYDelta)
//第一個參數fromXDelta爲動畫起始時 X座標上的移動位置
//第二個參數toXDelta爲動畫結束時 X座標上的移動位置
//第三個參數fromYDelta爲動畫起始時Y座標上的移動位置
//第四個參數toYDelta爲動畫結束時Y座標上的移動位置
設置動畫持續時間
myAnimation_Translate = new TranslateAnimation(10f, 100f, 10f, 100f);
myAnimation_Translate.setDuration(2000);
//設置時間持續時間爲 2000毫秒
4. RotateAnimation
RotateAnimation類對象定義
private RotateAnimation myAnimation_Rotate;
RotateAnimation類對象構造
RotateAnimation(float fromDegrees, float toDegrees,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
//第一個參數fromDegrees爲動畫起始時的旋轉角度
//第二個參數toDegrees爲動畫旋轉到的角度
//第三個參數pivotXType爲動畫在X軸相對於物件位置類型
//第四個參數pivotXValue爲動畫相對於物件的X座標的開始位置
//第五個參數pivotXType爲動畫在Y軸相對於物件位置類型
//第六個參數pivotYValue爲動畫相對於物件的Y座標的開始位置
myAnimation_Rotate = new RotateAnimation(0.0f, +350.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF, 0.5f);
設置動畫持續時間
myAnimation_Rotate.setDuration(3000);
//設置時間持續時間爲 3000毫秒
如何Java代碼中使用動畫效果
使用從View父類繼承過來的方法startAnimation()來爲View或是子類View等等添加一個動畫效果
public void startAnimation (Animation animation)
view.startAnimation(myAnimation_Alpha);
view.startAnimation(myAnimation_Scale);
view.startAnimation(myAnimation_Translate);
view.startAnimation(myAnimation_Rotate);
3: android sdk通過Interpolator 控制動畫的運行
首先要了解爲什麼需要插值器,因爲在補間動畫中,我們一般只定義關鍵幀(首幀或尾幀),然後由系統自動生成中間幀,生成中間幀的這個過程可以成爲“插值”。插值器定義了動畫變化的速率,提供不同的函數定義變化值相對於時間的變化規則,可以定義各種各樣的非線性變化函數,比如加速、減速等。下面是幾種常見的插值器:
Interpolator對象 | 資源ID | 功能作用 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速再減速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先回退一小步然後加速前進 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 在上一個基礎上超出終點一小步再回到終點 |
BounceInterpolator | @android:anim/bounce_interpolator | 最後階段彈球效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 週期運動 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 減速 |
LinearInterpolator | @android:anim/linear_interpolator | 勻速 |
OvershootInterpolator | @android:anim/overshoot_interpolator |
快速到達終點並超出一小步最後回到終點 |
<set android:interpolator="@android:anim/accelerate_interpolator">
...
</set>
<alpha android:interpolator="@android:anim/accelerate_interpolator"
.../>
<accelerateDecelerateInterpolator> 無
<accelerateInterpolator> android:factor 浮點值,加速速率,默認爲1
<anticipateInterploator> android:tension 浮點值,起始點後退的張力、拉力數,默認爲2
<anticipateOvershootInterpolator> android:tension 同上 android:extraTension 浮點值,拉力的倍數,默認爲1.5(2 * 1.5)
<bounceInterpolator> 無
<cycleInterplolator> android:cycles 整數值,循環的個數,默認爲1
<decelerateInterpolator> android:factor 浮點值,減速的速率,默認爲1
<linearInterpolator> 無
<overshootInterpolator> 浮點值,超出終點後的張力、拉力,默認爲2
下面我們就拿最後一個插值器來舉例:
<?xml version="1.0" encoding="utf-8"?>
<overshootInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:tension="7.0"/>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@anim/my_overshoot_interpolator"
.../>
我們可以實現Interpolator接口,因爲上面所有的Interpolator都實現了Interpolator接口,這個接口定義了一個方法:float getInterpolation(float input);
此方法由系統調用,input代表動畫的時間,在0和1之間,也就是開始和結束之間。
線性(勻速)插值器定義如下:
public float getInterpolation(float input) {
return input;
}
加速減速插值器定義如下:
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
有興趣的話,大家可以嘗試一下自定義一個插值器。
應用:
先來介紹一下旋轉動畫的使用,佈局文件/res/layout/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF">
<ImageView
android:id="@+id/piechart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/piechart"/>
<Button
android:id="@+id/positive"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="順時針"
android:onClick="positive"/>
<Button
android:id="@+id/negative"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="逆時針"
android:onClick="negative"/>
</LinearLayout>
我們定義了一個ImageView,用於顯示一個餅狀圖,演示旋轉動畫,然後定義了兩個按鈕,用以運行編碼實現的動畫。動畫定義文件/res/anim/rotate.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<rotate
android:fromDegrees="0"
android:toDegrees="+360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="5000"/>
</set>
最後再來看一下RotateActivity.java代碼:
public class RotateActivity extends Activity {
private int currAngle;
private View piechart;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rotate);
piechart = findViewById(R.id.piechart);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);
piechart.startAnimation(animation);
}
public void positive(View v) {
Animation anim = new RotateAnimation(currAngle, currAngle + 180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
/** 勻速插值器 */
LinearInterpolator lir = new LinearInterpolator();
anim.setInterpolator(lir);
anim.setDuration(1000);
/** 動畫完成後不恢復原狀 */
anim.setFillAfter(true);
currAngle += 180;
if (currAngle > 360) {
currAngle = currAngle - 360;
}
piechart.startAnimation(anim);
}
public void negative(View v) {
Animation anim = new RotateAnimation(currAngle, currAngle - 180, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
/** 勻速插值器 */
LinearInterpolator lir = new LinearInterpolator();
anim.setInterpolator(lir);
anim.setDuration(1000);
/** 動畫完成後不恢復原狀 */
anim.setFillAfter(true);
currAngle -= 180;
if (currAngle < -360) {
currAngle = currAngle + 360;
}
piechart.startAnimation(anim);
}
}
4.動畫的運行
模式
獨佔模式; 即程序主線程進入循環,根據動畫指令不斷刷新屏幕,直至動畫結束
終端模式: 即有單獨一個線程時間計數,每隔一定的時間向主線程發送通知,主線程接到通知後更新屏幕。
二:Frame Animation 動畫:
android通過AnimationDrawable來定義
可以在xml定義,也可以使用AnimationDrawable中的API定義,由於Tween Animation與Frame Aniamtion
有着很大的不同,因此xml定義的格式也不一樣,首先是 animation-list根節點,animation-list根節點中包含多個item子節點,每個item節點定義一幀動畫,當前幀的drawable資源和當前幀持續的時間
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource_name"
android:duration="integer" />
</animation-list>
需要注意的是:
<animation-list>元素是必須的,並且必須要作爲根元素,可以包含一或多個<item>元素;android:onshot如果定義爲true的話,此動畫只會執行一次,如果爲false則一直循環。
<item>元素代表一幀動畫,android:drawable指定此幀動畫所對應的圖片資源,android:druation代表此幀持續的時間,整數,單位爲毫秒。
我們新建一個名爲anim的工程,將四張連續的圖片分別命名爲f1.png,f2.png,f3.png,f4.png,放於drawable目錄,然後新建一個frame.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/f1" android:duration="300" />
<item android:drawable="@drawable/f2" android:duration="300" />
<item android:drawable="@drawable/f3" android:duration="300" />
<item android:drawable="@drawable/f4" android:duration="300" />
</animation-list>
我們可以將frame.xml文件放置於drawable或anim目錄,官方文檔上是放到了drawable中了,大家可以根據喜好來放置,放在這兩個目錄都是可以運行的。
我們定義了一個ImageView作爲動畫的載體,然後定義了兩個按鈕,分別是停止和啓動動畫。
接下來介紹一下如何通過加載動畫定義文件來實現動畫的效果。我們首先會這樣寫:
image = (ImageView) findViewById(R.id.frame_image);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
anim.start();
看似十分完美,跟官方文檔上寫的一樣,然而當我們運行這個程序時會發現,它只停留在第一幀,並沒有出現我們期望的動畫,也許你會失望的說一句:“Why?”,然後你把相應的代碼放在一個按鈕的點擊事件中,動畫就順利執行了,再移回到onCreate中,還是沒效果,這個時候估計你會氣急敗壞的吼一句:“What the fuck!”。但是,什麼原因呢?如何解決呢?
出現這種現象是因爲當我們在onCreate中調用AnimationDrawable的start方法時,窗口Window對象還沒有完全初始化,AnimationDrawable不能完全追加到窗口Window對象中,那麼該怎麼辦呢?我們需要把這段代碼放在onWindowFocusChanged方法中,當Activity展示給用戶時,onWindowFocusChanged方法就會被調用,我們正是在這個時候實現我們的動畫效果。當然,onWindowFocusChanged是在onCreate之後被調用的,如圖:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
anim.start();
}
如果在有些場合,我們需要用純代碼方式實現一個動畫,我們可以這樣寫:
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
Drawable drawable = getResources().getDrawable(id);
anim.addFrame(drawable, 300);
}
anim.setOneShot(false);
image.setBackgroundDrawable(anim);
anim.start();
學習不易,且學且珍惜。。。。。。。。
Interpolator對象 | 資源ID | 功能作用 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速再減速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先回退一小步然後加速前進 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 在上一個基礎上超出終點一小步再回到終點 |
BounceInterpolator | @android:anim/bounce_interpolator | 最後階段彈球效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 週期運動 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 減速 |
LinearInterpolator | @android:anim/linear_interpolator | 勻速 |
OvershootInterpolator | @android:anim/overshoot_interpolator |
快速到達終點並超出一小步最後回到終點 |