在Android開發中,我們常見一些很絢麗的動畫效果。這些動畫效果使得我們的應用用起來非常的絢麗。那麼今天就來講講Android開發中,常用的動畫效果吧。
在Android開發中,有幀動畫和補間動畫兩種
1、逐幀動畫是在時間幀上逐幀繪製幀內容,由於是一幀一幀的畫,所以逐幀動畫具有非常大的靈活性,幾乎可以表現任何想表現的內容。但是在開發中,我們不常用這個動畫。
2、與逐幀動畫相比,補間動畫具有以下幾個特點:首先,製作方法簡單方便。只需要爲動畫的第一個關鍵幀和最後一個關鍵幀創建內容,兩個關鍵幀之間幀的內容由Flash自動生成,不需要人爲處理。其次,相對於逐幀動畫來說,補間動畫更爲連貫自然。因爲逐幀動畫是由手工控制,幀與幀之間的過渡很可能會不自然、不連貫,而補間動畫除了兩個關鍵幀由手工控制外,中間的幀都由Flash自動生成,技術含量很高,因此過渡更爲自然連貫。最後,相對於逐幀動畫來說,補間動畫的文件更小,佔用內存少。
今天,我們詳細的講解補間動畫。所謂補間動畫,就是在兩個畫面跳轉的時候,執行的動畫。在Android開發中,我們在activity切換,fragment切換,dialog、PopupWindow以及使用WindowManager的時候,我們都會有需要動畫來是的切換或者展示效果更佳的絢麗。補間動畫有四種:平移、縮放、旋轉、漸變。
一、在代碼中實現動畫效果,這裏博主自定義了一個Animation提供者,直接上代碼:
/**
* @ClassName: FreedomAnimationUtils
* @author victor_freedom ([email protected])
* @createddate 2014年12月22日 下午9:57:21
* @Description: 動畫工具提供者
*/
public class FreedomAnimationUtils {
/**
* @Title: getRotateAnimation
* @Description: 旋轉動畫
* @param fromDegrees
* 起始角度
* @param toDegrees
* 結束角度
* @param pivotXType
* 相對於什麼位置(Animation.RELATIVE_TO_SELF(相對於父控件),
* Animation.RELATIVE_TO_SELF(相對於自己),Animation.ABSOLUTE(絕對位置))
* @param pivotXValue
* 以什麼爲中心點
* @param pivotYType
* 同上
* @param pivotYValue
* 同上
* @param durationMillis
* 維持時間
* @return
* @throws
*/
public static Animation getRotateAnimation(float fromDegrees,
float toDegrees, int pivotXType, float pivotXValue, int pivotYType,
float pivotYValue, long durationMillis) {
RotateAnimation rotate = new RotateAnimation(fromDegrees, toDegrees,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
// 重複模式:1、重新開始;2、從尾開始
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatMode(Animation.REVERSE);
// 維持時間
rotate.setDuration(durationMillis);
// 完畢之後是否保持狀態
rotate.setFillAfter(true);
return rotate;
}
/**
* @Title: getAlphaAnimation
* @Description: 透明度
* @param fromAlpha
* @param toAlpha
* @param durationMillis
* @return
* @throws
*/
public static Animation getAlphaAnimation(float fromAlpha, float toAlpha,
long durationMillis) {
AlphaAnimation alpha = new AlphaAnimation(fromAlpha, toAlpha);
// 重複次數
alpha.setRepeatCount(2);
// 重複模式:1、重新開始;2、從尾開始
alpha.setRepeatMode(Animation.RESTART);
alpha.setRepeatMode(Animation.REVERSE);
// 維持時間
alpha.setDuration(durationMillis);
// 完畢之後是否保持狀態
alpha.setFillAfter(true);
return alpha;
}
/**
* @Title: getScaleAnimation
* @Description: 縮放動畫
* @param fromX
* 起始大小
* @param toX
* 縮放後大小
* @param fromY
* 起始大小
* @param toY
* 縮放後大小
* @param pivotXType
* 縮放參照物,相對於哪一個位置(Animation.ABSOLUTE,
* Animation.RELATIVE_TO_SELF,or Animation.RELATIVE_TO_PARENT);
* @param pivotXValue
* 縮放的時候以哪一個位置爲中心點,一般寫0.5f,相對於控件中央
* @param pivotYType
* @param pivotYValue
* @param durationMillis
* @return
* @throws
*/
public static Animation getScaleAnimation(float fromX, float toX,
float fromY, float toY, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue, long durationMillis) {
ScaleAnimation scale = new ScaleAnimation(1.0f, 1.5f, 1.0f, 1.5f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
scale.setDuration(durationMillis);
return scale;
}
/**
* @Title: getTranslateAnimation
* @Description: TODO
* @param fromXDelta
* 這個參數表示動畫開始的點離當前View X座標上的差值;
* @param toXDelta
* 這個參數表示動畫結束的點離當前View X座標上的差值;
* @param fromYDelta
* 這個參數表示動畫開始的點離當前View Y座標上的差值;
* @param toYDelta
* 這個參數表示動畫開始的點離當前View Y座標上的差值;
* @param durationMillis
* @return
* @throws
*/
public static Animation getTranslateAnimation(float fromXDelta,
float toXDelta, float fromYDelta, float toYDelta,
long durationMillis) {
TranslateAnimation translate = new TranslateAnimation(fromXDelta,
toXDelta, fromYDelta, toYDelta);
translate.setDuration(durationMillis);
translate.setFillAfter(true);
return translate;
}
/**
* @Title: getTranslateAnimations
* @Description: TODO
* @param fromXType
* 第一個參數是x軸方向的值的參照(Animation.ABSOLUTE,
* Animation.RELATIVE_TO_SELF,or Animation.RELATIVE_TO_PARENT);
* @param fromXValue
* 第二個參數是第一個參數類型的起始值;
* @param toXType
* 第三個參數與第四個參數是x軸方向的終點參照與對應值
* @param toXValue
* 結束位置的值
* @param fromYType
* @param fromYValue
* @param toYType
* @param toYValue
* @param durationMillis
* @return
* @throws
*/
public static Animation getTranslateAnimations(int fromXType,
float fromXValue, int toXType, float toXValue, int fromYType,
float fromYValue, int toYType, float toYValue, long durationMillis) {
TranslateAnimation translate = new TranslateAnimation(fromXType,
fromXValue, toXType, toXValue, fromYType, fromYValue, toYType,
toYValue);
translate.setDuration(durationMillis);
translate.setFillAfter(false);
return translate;
}
/**
* @Title: getAnimationSet
* @Description: 組合動畫
* @return
* @throws
*/
public static AnimationSet getAnimationSet() {
// 頂一個一個set
AnimationSet animationSet = new AnimationSet(false);
ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
sa.setDuration(2000);
sa.setRepeatCount(2);
sa.setRepeatMode(Animation.REVERSE);
RotateAnimation ra = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF,
1.0f);
ra.setDuration(2000);
ra.setRepeatCount(2);
ra.setRepeatMode(Animation.REVERSE);
TranslateAnimation ta = new TranslateAnimation(
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 1.0f,
Animation.RELATIVE_TO_PARENT, 0.0f,
Animation.RELATIVE_TO_PARENT, 1.0f);
ta.setDuration(2000);
ta.setRepeatCount(2);
ta.setRepeatMode(Animation.REVERSE);
// 將定義好的動畫直接加入到set中
animationSet.addAnimation(sa);
animationSet.addAnimation(ra);
animationSet.addAnimation(ta);
return animationSet;
}
}
二、在XML文件中自定義動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<!--
%:相對於view自身位置移動,相當於Animation.RELATIVE_TO_SELF
%p:相對於父元素,參考的是父元素,相當於Animation.RELATIVE_TO_PARENT
什麼都不寫相當於Animation.ABSOLUTE
其中interpolator是一個函數計算過程,是動畫播放過程中的變化率
Android提供的幾個定義好的類直接使用,有興趣的朋友也可以自己去自定義變化率
AccelerateDecelerateInterpolator 在動畫開始與介紹的地方速率改變比較慢,在中間的時侯加速
AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速
CycleInterpolator 動畫循環播放特定的次數,速率改變沿着正弦曲線
DecelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始減速
LinearInterpolator 在動畫的以均勻的速率改變
-->
<scale
android:duration="200"
android:fillAfter="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="restart"
android:toXScale="1.0"
android:toYScale="1.0" />
<alpha
android:duration="200"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fillAfter="true"
android:fromXDelta="0%"
android:fromYDelta="0%"
android:repeatCount="2"
android:repeatMode="restart"
android:toXDelta="100%"
android:toYDelta="100%" />
<rotate
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="2"
android:repeatMode="restart"
android:toDegrees="100" />
</set>
調用XML編寫的動畫只需要寫Animation animation = AnimationUtils.loadAnimation(this,R.anim.xxx);即可
三、Anctivity切換動畫:
對於Activity切換動畫,我們只需要在startActivity之後,加上一句即可:
Intent intent=new Intent(PathButtonActivity.this,MainActivity.class);
startActivity(intent);
//第一個參數爲啓動時動畫效果,第二個參數爲退出時動畫效果
overridePendingTransition(R.anim.fade, R.anim.hold);
四、Fragment切換動畫
在使用fragment切換動畫的時候要特別注意,如果你的fragment不是V4包的fragment,那麼使用切換的動畫資源必須放置在res\animator的目錄下,且根標籤是<set><objectAnimator><valueAnimator>之一,至於爲什麼,有興趣的朋友可以去研究一下Property Animation和View Animation的區別。因爲我們常用的fragment肯定是包含V4包的,兼容性比較好,所以,我們只講在anim文件夾下的動畫使用。看代碼:
FragmentTransaction fragmentTransaction = mFragmentManager
.beginTransaction();
fragmentTransaction.setCustomAnimations(
R.anim.push_left_in,
R.anim.push_left_out,
R.anim.push_left_in,
R.anim.push_left_out);
fragmentTransaction.add(R.id.container, mTextFragmentOne);
在切換fragment使用動畫的時候,必須在add或者replace之前調用setCustomAnimations()方法。
五、Dialog、PopupWindow以及WindowManager彈窗動畫效果
這三者的實現動畫效果方式,其實是差不多的,都需要先定義一個風格style,看代碼:
<style name="freedom_anim_style">
<item name="android:windowEnterAnimation">@anim/popshow_anim</item> <!-- 指定顯示的動畫xml -->
<item name="android:windowExitAnimation">@anim/pophidden_anim</item> <!-- 指定消失的動畫xml -->
</style>
有了這個風格style之後,就方便很多了
1、Dialog實現彈出動畫:
AlertDialog.Builder b = new Builder(this);
b.create().getWindow().setWindowAnimations(R.style.freedom_anim_style);
2、PopupWindow實現彈出動畫:
PopupWindow p = new PopupWindow();
p.setAnimationStyle(R.style.freedom_anim_style);
3、WindowManger添加窗體實現彈出動畫:(這個稍微多幾步,但是其實原理和之前兩個彈窗的底層是一樣的)我們以添加一個view爲例子
view = View.inflate(context, R.layout.freedom, null);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, // 沒有邊界
PixelFormat.TRANSLUCENT);
lp.gravity = Gravity.TOP;
// 重要 這就是添加動畫的地方
lp.windowAnimations = R.style.freedom_anim_style;
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(view, lp);
到此Android開發中常用的動畫以及使用場景方式已經講解完畢,希望能夠幫助到看到此篇文章的人。