??android中酷炫的效果,都離不開動畫的支持喷舀。這里我們詳細介紹一下android中動畫的分類。android的中動畫分為幀動畫淋肾、補間動畫硫麻、屬性動畫。原理各不相同樊卓,實現(xiàn)的效果也大不相同拿愧。下面一一講解三種動畫。
幀動畫
??幀動畫顧名思義就是通過順序一幀一幀播放圖片從而產(chǎn)生動畫效果碌尔,效果類似放電影浇辜。該動畫缺點比較明顯,就是如果圖片過大過多會導致OOM唾戚。幀動畫xml文件放置在drawable目錄下而非anim文件夾下柳洋。
<?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/ic_launcher_background"
android:duration="150" />
<item
android:drawable="@drawable/ic_launcher_background"
android:duration="150" />
</animation-list>
補間動畫
??補間動畫是通過對view進行旋轉(zhuǎn)、縮放叹坦、漸變熊镣、透明度變化,而達到的一種動畫效果。是一種漸進式動畫绪囱。并且可以通過組合以上四種操作测蹲,完成復雜的自定義動畫效果。缺點就是只是改變的view的展示狀態(tài)毕箍,但是不會改變view的位置弛房。例如我們將一個button通過位移想左移動100dp,然后停留在終點而柑。但是我們可以發(fā)現(xiàn)展示的位置button點擊無效果文捶,不可以交互。而在button原始位置空白的地方點擊會觸發(fā)button的點擊效果媒咳。也就是button本質(zhì)還是在原來位置粹排,只是展示左移了100dp。
屬性說明
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fillAfter="true"
android:fillBefore="true"
android:interpolator="@[package:]anim/interpolator_resource"
android:repeatMode="restart | reverse"
android:repeatCount = “0”
android:shareInterpolator="true"
android:startOffset="float">
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:fromYScale="float"
android:pivotX="float"
android:pivotY="float"
android:toXScale="float"
android:toYScale="float" />
<rotate
android:fromDegrees="float"
android:pivotX="float"
android:pivotY="float"
android:toDegrees="float" />
<translate
android:fromXDelta="float"
android:fromYDelta="float"
android:toXDelta="float"
android:toYDelta="float" />
</set>
通用屬性說明:
- android:duration=""動畫時長涩澡,單位毫秒
- android:fillAfter="true"動畫完成后是否停留在結(jié)束位置顽耳,默認false
- android:fillBefore="true"動畫完成后是否停留在起點位置。默認true妙同,優(yōu)先級低于fillAfter
- android:interpolator為動畫的變化速度【可以單獨設置射富,可以直接放在set里面】
可以設置多種速度變化方式,這里只列出勻速粥帚、加速胰耗、減速
勻速 @android:anim/linear_interpolator
加速 @android:anim/accelerate_interppolator
減速 @android:anim/decelerate_interpolator - android:repeatMode="restart | reverse"動畫重復策略 restart從起點位置(正序)重復,reverse從結(jié)束位置(倒序)重復
- android:repeatCount = “0”重復次數(shù) “infinite”為無線重復
- android:shareInterpolator="true"動畫集合中的動畫是否公用一個差值器
- android:startOffset="float"動畫延遲時間
透明度動畫
透明度動畫芒涡,通過改變view的透明度展示動畫柴灯。對應AlphaAnimation和<alpha>xml標簽
- android:fromAlpha="float" 起始透明度,取值范圍(-1.0~1.0)
- android:toAlpha="float"結(jié)束時透明度费尽,取值范圍(-1.0~1.0)
縮放動畫
縮放動畫赠群,通過修改view的大小展示動畫。對應ScaleAnimation類和<scale>xml表情
- android:fromXScale="float"動畫在水平方向X的起始縮放倍數(shù)
- android:fromYScale="float"動畫在水平方向Y的結(jié)束縮放倍數(shù)
- android:toXScale="float"動畫在豎直方向X的結(jié)束縮放倍數(shù)
- android:toYScale="float"動畫在豎直方向Y的結(jié)束縮放倍數(shù)
// 0.0表示收縮到?jīng)]有旱幼;1.0表示正常無伸縮
// 值小于1.0表示收縮查描;值大于1.0表示放大 - android:pivotX="float"縮放中心點的x坐標
- android:pivotY="float"縮放中心點的y坐標
// pivotX pivotY,可取值為數(shù)字,百分比柏卤,或者百分比p
// 設置為數(shù)字時(如50)叹誉,軸點為View的左上角的原點在x方向和y方向加上50px的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.ABSOLUTE闷旧。
// 設置為百分比時(如50%),軸點為View的左上角的原點在x方向加上自身寬度50%和y方向自身高度50%的點钧唐。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_SELF忙灼。
// 設置為百分比p時(如50%p),軸點為View的左上角的原點在x方向加上父控件寬度50%和y方向父控件高度50%的點。在Java代碼里面設置這個參數(shù)的對應參數(shù)是Animation.RELATIVE_TO_PARENT
旋轉(zhuǎn)動畫
通過旋轉(zhuǎn)view展示動畫该园。對應RotateAnimation類和<rotate>xml標簽
- android:fromDegrees="float"動畫開始時 視圖的旋轉(zhuǎn)角度(正數(shù) = 順時針酸舍,負數(shù) = 逆時針)
- android:toDegrees="float"動畫結(jié)束時 視圖的旋轉(zhuǎn)角度(正數(shù) = 順時針,負數(shù) = 逆時針)
- android:pivotX="float"旋轉(zhuǎn)中心點的x坐標 具體如上縮放中心點參數(shù)解釋
- android:pivotY="float"旋轉(zhuǎn)中心點的y坐標 具體如上縮放中心點參數(shù)解釋
平移動畫
平移動畫里初,更改view的展示位置展示動畫啃勉。對應TranslateAnimation類和<translate>xml表情
- android:fromXDelta="float"view在水平x方向的起始值
- android:fromYDelta="float"view在水平y(tǒng)方向的起始值
- android:toXDelta="float"view在水平x方向的結(jié)束值
- android:toYDelta="float" view在水平y(tǒng)方向的結(jié)束值
具體動畫的使用
應用動畫xml配置
TextView textDemo = findViewById(R.id.text_demo);
Animation animation = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_animation_test);
textDemo.startAnimation(animation);
使用java類配置動畫,具體參數(shù)類同xml參數(shù)双妨,建議使用xml配置動畫
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 2.0f);
textDemo.startAnimation(alphaAnimation);
監(jiān)聽動畫
alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
//動畫開始回調(diào)
}
@Override
public void onAnimationEnd(Animation animation) {
//動畫結(jié)束回調(diào)
}
@Override
public void onAnimationRepeat(Animation animation) {
//動畫重復時回調(diào)
}
});
View動畫特殊使用場景
- Activity 的切換效果
- 使用
public void overridePendingTransition(int enterAnim, int exitAnim)
給activity切換添加動畫效果淮阐。調(diào)用時機在startActivity()或者finish()方法之后調(diào)用,否則不起作用刁品。 - 配置theme的style
<style name="AnimationActivity" parent="@android:style/Animation.Activity"> <item name="android:activityOpenEnterAnimation">@anim/push_left_in</item> <item name="android:activityCloseExitAnimation">@anim/push_left_in</item> <item name="android:activityOpenExitAnimation">@anim/push_left_out</item> <item name="android:activityCloseEnterAnimation">@anim/push_left_out</item> </style>
- 使用
- Fragement 的切換效果
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.setCustomAnimations()
- 視圖組(ViewGroup)中子元素的出場效果
簡單來說就是可以在 ViewGroup 的添加一個入場動畫泣特,這個 ViewGroup 的所有子元素都會按照你設計的順序執(zhí)行一遍動畫,至于子元素的范圍目測是直接子元素才行挑随。常見的有
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/rotate_animation_test"
android:delay="20"
android:interpolator=""
android:animationOrder="random"/>
- android:animation="@anim/rotate_animation_test"
- android:delay="20"是子元素開始動畫的時間延遲状您,比如子元素入場動畫的時間周期為300ms,那么0.5就代表每個子元素都需要延遲150ms才能播放入場動畫兜挨「嗝希總體來說柒桑,第一個子元素延遲150ms開始播放入場動畫,第二個子元素延遲300ms開始播放入場動畫,依次類推仇奶。
- android:animationOrder="random" 子元素入場順序reverse倒序 normal正常 random隨機
應用:
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dp"
android:layoutAnimation="@anim/rotate_animation_test"
android:layout_centerInParent="true">
......子view
</RelativeLayout>
屬性動畫
??屬性動畫本質(zhì)是通過改變對象的屬性(例如:x,y等屬性),來實現(xiàn)動畫的,所以基本上是無所不能的氯庆,只要對象有這個屬性仁讨,就能實現(xiàn)動畫效果。屬性動畫是在api11的新特性,通過動態(tài)的改變view的屬性從而達到動畫效果礁哄。雖然可以使用nineoldandroid庫向下兼容之拨,但是兼容本質(zhì)是使用補間動畫完成烁竭,也就是說不會更改view的屬性睬魂,也不會更改view的位置氯哮。屬性動畫比較常用的類: ValueAnimator姆打、ObjectAnimator肠虽、AnimationSet评抚,其中ObjectAnimator是ValueAnimator的子類啸如,而AnminationSet是動畫集合
單個動畫
ObjectAnimator animator = ObjectAnimator
.ofInt(textDemo, "backgroundColor", 0XffFF0000, 0Xff0000FF)
.setDuration(2000);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.setRepeatCount(10);
animator.start();
動畫集合
AnimatorSet animatorSet = new AnimatorSet();
ValueAnimator translationX = ObjectAnimator.ofFloat(textDemo, "translationX", 200f);
ValueAnimator animator = ObjectAnimator
.ofInt(textDemo, "backgroundColor", 0XffFF0000, 0Xff0000FF);
animatorSet.playTogether(translationX,animator);
animatorSet.setDuration(1000).start();
動畫配置同樣可以使用xml配置帘不,參數(shù)類似,這里不做詳細說明寞焙。
差值器和估值器
差值器(Interpolator)
根據(jù)時間流逝百分比計算當前屬性改變百分比储狭。同xml配置動畫中的 android:interpolator
屬性配置,常見有LinearInterpolator(線性差值器)捣郊、AccelerateDecelerateInterpolator(加速減速差值器)
等辽狈。自定義需要實現(xiàn)Interpolator
或者TimeInterpolator
。Interpolator接口繼承TimeInterpolator呛牲。
// Interpolator接口
public interface Interpolator extends TimeInterpolator{
// 內(nèi)部只有一個方法
float getInterpolation(float input) {
// 參數(shù)說明
// input值值變化范圍是0-1刮萌,且隨著動畫進度(0% - 100% )均勻變化
// 即動畫開始時,input值 = 0娘扩;動畫結(jié)束時input = 1
// 而中間的值則是隨著動畫的進度(0% - 100%)在0到1之間均勻增加
...// 插值器的計算邏輯
return xxx着茸;
// 返回的值就是用于估值器繼續(xù)計算的fraction值,下面會詳細說明
}
// TimeInterpolator接口
// 同上
public interface TimeInterpolator {
float getInterpolation(float input);
}
估值器(TypeEvaluator)
根據(jù)當前屬性改變百分比計算改變后的屬性值琐旁。屬性動畫特有的屬性涮阔。自定義估值器需要實現(xiàn)TypeEvaluator
接口。
public interface TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
// 參數(shù)說明
// fraction:插值器getInterpolation()的返回值
// startValue:動畫的初始值
// endValue:動畫的結(jié)束值
....// 估值器的計算邏輯
return xxx旋膳;
// 賦給動畫屬性的具體數(shù)值
// 使用反射機制改變屬性變化
// 特別注意
// 那么插值器的input值 和 估值器fraction有什么關系呢澎语?
// 答:input的值決定了fraction的值:input值經(jīng)過計算后傳入到插值器的getInterpolation(),然后通過實現(xiàn)getInterpolation()中的邏輯算法验懊,根據(jù)input值來計算出一個返回值擅羞,而這個返回值就是fraction了
}
}
可以對任意屬性做屬性動畫,屬性動畫要求動畫作用的對象提供該屬性的get()和set()方法义图。因為屬性動畫本質(zhì)就是根據(jù)外界傳遞的對象屬性的初始值和終點值减俏,然后根據(jù)估值器和差值器計算屬性值,不斷調(diào)用屬性的set方法碱工,通過時間的推移所傳遞的值娃承,越來越近終點值奏夫。
注意:
- 對象屬性必須提供對應的set方法,而且如果沒有初始值傳入的情況下必須要設置get方法历筝,因為 系統(tǒng)要獲取初始值酗昼,如果沒有滿足條件則程序cash
- 對象屬性的set方法對屬性做出改變,需要能夠通過某種方法表示出來梳猪。帶來ui展示效果的改變麻削。否則動畫不會生效。
ValueAnimator
使用ValueAnimator通過監(jiān)聽動畫過程春弥,自己改變對象屬性完成動畫
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.setDuration(2000);//動畫持續(xù)時間
valueAnimator.setRepeatCount(0);//重復次數(shù)
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//重復方式呛哟,
valueAnimator.setStartDelay(20);//開始前延遲時間
valueAnimator.setEvaluator(new IntEvaluator());//估值器
valueAnimator.setInterpolator(new LinearInterpolator());//差值器
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//獲取當前動畫屬性值,即1~100
Integer animatedValue = (Integer) animation.getAnimatedValue();
//獲取動畫的百分比
float animatedFraction = animation.getAnimatedFraction();
ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
int width = layoutParams.width;
int height = layoutParams.height;
layoutParams.height = height + 1;
layoutParams.width=width+1;
Log.e(TAG,"animatedValue: "+animatedValue+" animatedFraction : "+animatedFraction
+" width : "+layoutParams.width+" height : "+layoutParams.height);
textView.requestLayout();
}
});
valueAnimator.start();
}
注意事項
- OOM注意匿沛,在幀動畫中如果圖片過大扫责、數(shù)量過多容易出現(xiàn)
- 內(nèi)存泄漏, 切記在activity銷毀時逃呼,停止動畫鳖孤。否則一些無限循環(huán)動畫將導致activity不能釋放而內(nèi)存泄漏。出現(xiàn)在屬性動畫中蜘渣,view動畫不存在此類問題
- 兼容性問題淌铐,屬性動畫出現(xiàn)在android3.0以后,雖然有兼容包蔫缸,但是內(nèi)部實行是view動畫腿准,注意視覺位置和真實位置差異
- View動畫即補間動畫,是改變view的視覺位置拾碌,改變view的影像展示位置吐葱,而不改變真實位置。注意交互體驗校翔〉芘埽可能會出現(xiàn)view動畫結(jié)束后,view無法隱藏的問題及setVisibility(View.GONE)失效防症。此時調(diào)用view.clearAnimation()清除動畫孟辑。可修復此類問題
- 注意適配蔫敲,動畫中的屬性都是px的但是切換展示過程中使用dp饲嗽,
- 交互問題,在android3.0以前屬性動畫和view動畫都是改變影像位置奈嘿,不改變真實位置貌虾,例如點擊依舊在原位置點擊響應,而不是新位置裙犹,在3.0以后屬性動畫view真實位置隨著影像位置而變交互即在移動后的位置尽狠,而view動畫仍然在原始位置衔憨。
- 使用動畫的過程中,建議使用硬件加速袄膏,提高動畫的流暢性践图。