本文已經收錄到個人Github我的博客,歡迎大佬們光臨寒舍:php
個人GIthub博客html
筆者在以前進階之路 | 奇妙的View之旅中,說起View滑動的七種方式
的時候簡單說到Animation
,想必看過的讀者們已經對Animation
有一個簡單的印象。java
動畫,對於一個APP來講很是重要,如今市面上使用的用戶比較多的APP,無一不是採用了各類豐富多彩的動畫效果;在應用中善於使用動畫,不只讓APP的體驗更上一層樓,還能緊緊抓住用戶的心!android
而做爲開發者的咱們,必定要對動畫有必定深度的瞭解,在平常的學習或者工做中多多嘗試動畫,以提升應用程序的美觀度和易用性!git
什麼,你不信動畫很重要....反手甩你一個對比視頻:過渡動畫有多重要?github
View
動畫(視圖動畫)分爲兩部分:bash
- 補間動畫
- 幀動畫
Q1:主要的變換效果app
名稱 | 標籤 | 子類 | 效果 |
---|---|---|---|
平移動畫 | translate |
TranslateAnimation |
移動View |
縮放動畫 | scale |
ScaleAnimation |
放大或縮小View |
旋轉動畫 | rotate |
RotateAnimation |
旋轉View |
透明度動畫 | alpha |
AlphaAnimation |
改變View的透明度 |
注意:View動畫的View移動只是視覺效果,並不能真正的改變view的位置。dom
Q2:動畫的建立ide
對於View動畫建議採用
XML
來定義,由於XML
可讀性更好
建立方法一:經過XML
定義:
XML
文件建立在res/anim/
下set
,子節點translate
、scale
、rotate
、alpha
,分別對應四種View動畫:<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="true" android:fillAfter="true">
<translate android:fromXDelta="float" android:toXDelta="float" android:fromYDelta="float" android:toYDelta="float"/>
<scale android:fromXScale="float" android:toXScale="float" android:fromYScale="float" android:toYScale="float" android:pivotX="float" android:pivotY="float"/>
<rotate android:fromDegrees="float" android:toDegrees="float" android:pivotY="float" android:pivotX="float"/>
<alpha android:fromAlpha="float" android:toAlpha="float"/>
</set>
複製代碼
接下來分別解釋各個節點下屬性含義:
A.set
:表示動畫集合,對應AnimationSet
類
interpolator
:表示動畫集合所採用的插值器,影響動畫的速度。能夠不指定,默認是accelerate_decelerate_interpolate
(加速減速插值器)。下文會詳細介紹插值器的相關知識。shareInterpolator
:表示集合中的動畫是否和集合共享一個插值器。若是集合不指定插值器, 那麼子動畫就須要單獨制定所需的插值器或者使用默認值。fillAfter
:表示動畫結束時是否保持動畫結束時的狀態B.translate
:表示平移動畫,對應TranslateAnimation
類
android:fromXDelta
:動畫起始時X座標上的位置。android:toXDelta
:動畫結束時X座標上的位置。android:fromYDelta
:動畫起始時Y座標上的位置。android:toYDelta
:動畫結束時Y座標上的位置。注意:以上四個屬性以及後面幾個相似屬性的取值多是數值、百分數、百分數p,各自含義是:
- 50:以View左上角爲原點沿座標軸正方向偏移50px。
- 50%:以View左上角爲原點沿座標軸正方向偏移View寬/高度的50%。
- 50%p:以View左上角爲原點沿座標軸正方向偏移父(parent)控件寬/高度的50%。區別如圖:
C.scale
:表示縮放動畫,對應ScaleAnimation
類
fromXScale
:動畫起始時X座標上的伸縮尺寸toXScale
:動畫結束時X座標上的伸縮尺寸fromYScale
:動畫起始時Y座標上的伸縮尺寸toYScale
:屬性爲動畫結束時Y座標上的伸縮尺寸以上四個屬性值的值含義:
值=0.0 :表示收縮到沒有
值<1.0 :表示收縮
值=1.0 :表示無伸縮
值>1.0 :表示放大
pivotX
:動畫相對於物件的X座標的開始位置pivotY
:動畫相對於物件的Y座標的開始位置以上兩個屬性值表示縮放的軸點:從0%-100%中取值。
D.rotate
:表示旋轉動畫,對應RotateAnimation
類。
fromDegrees
:動畫起始時物件的角度 (0度指X軸正方向所在方向)toDegrees
:動畫結束時物件旋轉的角度以上兩個屬性共同肯定旋轉方向,原則是:當角度(to-from)爲負數時表示逆時針旋轉,反之。
pivotY
:動畫旋轉的軸點的X座標pivotX
:動畫旋轉的軸點的Y座標E.alpha
:表示透明度動畫,對應AlphaAnimation
類
fromAlpha
:動畫起始時透明度toAlpha
:動畫結束時透明度以上兩個屬性值:從0-1中取值。注意:
- 值=0.0 :表示徹底透明
- 值=1.0 :表示徹底不透明
以上四類補間動畫除了各自的特有屬性外,它們的共有屬性有:
在xml
聲明好以後,接下來只要在代碼中startAnimation(animation)
開始動畫便可,代碼以下:
Animation animation = AnimationUtils.loadAnimation(this, R.anim.XXX);
mView.startAnimation(animation);
複製代碼
同時,可經過Animation的setAnimationListener(new AnimationListener(){...})
給動畫添加過程監聽,這樣在動畫開始、結束和每一次循環時均可在回調方法中監聽到。接口代碼以下:
public static interface AnimationListener {
//動畫開始
void onAnimationStart(Animator animation);
//動畫結束
void onAnimationEnd(Animator animation);
//動畫重複
void onAnimationRepeat(Animator animation);
}
複製代碼
建立方法二: 經過Java代碼動態建立
TranslateAnimation
、RotateAnimation
、ScaleAnimation
或AlphaAnimation
對象。View.startAnimation()
方法開啓動畫Animation.setAnimationListener()
設置動畫的監聽器Q3:綜合實例
A1:平移:
//法一:xml定義
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="100%" android:toYDelta="100%">
</translate>
//在MainActivity中調用
Animation translateAnim = AnimationUtils.loadAnimation(this, R.anim.view_anim_translate);
mImageView.startAnimation(translateAnim);
複製代碼
//法二:java代碼建立 RELATIVE_TO_SELF表示相對自身View
TranslateAnimation translateAnimation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 1,
Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 1);
translateAnimation.setDuration(2000);
mImageView.startAnimation(translateAnimation);
}
複製代碼
A2:縮放:
//法一:xml定義
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="0.5" android:toYScale="0.5">
</scale>
//在MainActivity中調用
Animation scaleAnim = AnimationUtils.loadAnimation(this, R.anim.view_anim_scale);
mImage.startAnimation(scaleAnim);
複製代碼
//法二:java代碼建立
ScaleAnimation scaleAnimation = new ScaleAnimation(
1, 0.5f,
1, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(2000);
mImageView.startAnimation(scaleAnimation);
複製代碼
A3: 旋轉:
//法一:xml定義
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%">
</rotate>
//在MainActivity中調用
Animation rotateAnim = AnimationUtils.loadAnimation(this, R.anim.view_anim_rotate);
mImageView.startAnimation(rotateAnim);
複製代碼
//法二:java代碼建立
RotateAnimation rotateAnimation = new RotateAnimation(
0, 360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setDuration(2000);
mImageView.startAnimation(rotateAnimation);
複製代碼
效果:圖片在2s內以圖片中心爲軸點,順時針旋轉360°,即完整轉一圈。
A4:透明度:
//法一:xml定義
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromAlpha="1.0" android:toAlpha="0">
</alpha>
//在MainActivity中調用
Animation alphaAnim = AnimationUtils.loadAnimation(this, R.anim.view_anim_alpha);
mImageView.startAnimation(alphaAnim);
複製代碼
//法二:java代碼建立
AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
alphaAnimation.setDuration(2000);
mImageView.startAnimation(alphaAnimation);
複製代碼
效果:圖片在2s內從有到無。
A5:動畫集合:
//法一:xml定義
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="true" >
<translate android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="100%" android:toYDelta="100%"> />
<scale android:duration="2000" android:fromXScale="1.0" android:fromYScale="1.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="0.5" android:toYScale="0.5" />
<rotate android:duration="2000" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"/>
<alpha android:duration="2000" android:fromAlpha="1.0" android:toAlpha="0"/>
</set>
//在MainActivity中調用
Animation setAnim = AnimationUtils.loadAnimation(this, R.anim.view_anim_set);
mImageView.startAnimation(setAnim);
複製代碼
效果:以上四種動畫效果的疊加。圖片在2s內邊向右下角移動、邊縮小、邊旋轉、邊下降透明度至消失。
實際項目中以上幾種動畫並不能知足咱們的需求,這時就須要自定義補間動畫
步驟:
1.繼承Animation
2.重寫initialize()
--->用於初始化
3.重寫applyTransformation()
--->用於進行矩陣變換
常常須要藉助Camera來簡化矩陣變換
View動畫除了可做用在某個View對象上, 還能夠用在特殊的場景,例如:
控制
ViewGroup
的子View
的出場效果
Activity
的切換效果接下來將依次介紹:
A1:子View
出場動畫
ListView
、GridView
、RecyclerView
LayoutAnimation
XML
文件建立在res/anim/
下layoutAnimation
,經常使用屬性:layoutAnimation
|- delay="float"
|- animationOrder="[normal|reverse | random]"
|- animation="[@anim/res_id]"
複製代碼
①delay
:表示子元素開始動畫的延遲時間。
好比,子元素入場動畫的時間週期是300ms,那麼該屬性值=0.5就表示每一個子元素都須要延遲150ms才能播放入場動畫。
②animationOrder
:表示子元素動畫的播放順序。可選模式:normal
(正常順序)、random
(隨機順序)、reverse
(倒序)。
③animation
:爲子元素指定具體的入場動畫。
法一:xml定義,分兩步
step1
:定義layoutAnimation
動畫
// res/anim/anim_layout.xml
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/anim_item"
android:delay="0.5"
android:animationOrder="normal">
</layoutAnimation>
// res/anim/anim_item.xml 效果:子項從右邊進入
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:shareInterpolator="true"
android:interpolator="@android:anim/accelerate_interpolator">
<alpha android:fromAlpha="0" android:toAlpha="1" /> <translate android:fromXDelta="100%" android:toXDelta="0" /> </set> 複製代碼
step2
:爲ViewGroup
設置android:layoutAnimation
屬性, 這裏假設爲Listview
:
//activity_main.xml
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layout"/>
複製代碼
法二:java代碼建立,經過LayoutAnimation
類綁定
// res/anim/anim_item.xml
<set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:shareInterpolator="true" android:interpolator="@android:anim/accelerate_interpolator">
<alpha android:fromAlpha="0" android:toAlpha="1" />
<translate android:fromXDelta="100%" android:toXDelta="0" />
</set>
複製代碼
//main.java
//和上述xml定義方法的效果相同
Animation animation = AnimationUtils.loadLayoutAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);//對應android:animation屬性
controller.setDelay(0.5);//對應android:delay屬性
controller.setOrder(LayoutAnimationController.ORDER_NORMAL); //對應android:animationOrder屬性
listView.setLayoutAnimation(controller);//對應android:layoutAnimation屬性
複製代碼
A2:Activity的切換效果
res/anim/
下overridePendingTransition(int inAnim, int outAnim)
方法
- 參數含義:(進入的Activity所需進行的動畫id,退出的Activity所需進行的動畫id)
- 該方法調用在
startActivity()
或finish()
之後才生效。例如:startActivity(intent); overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim); 複製代碼
幀動畫也是View動畫的一種,它會按照順序播放一組預先定義好的圖片。對應類
AnimationDrawable
。其中
AnimationDrawable
,筆者在進階之路 | 奇妙的Drawable之旅的文章末尾處也提到過。
Q1:幀動畫的建立
A1:經過xml
定義:
res/drawable/
下。animation-list
,屬性android:oneshot
表示是否執行一次;子節點item
下可設置輪播的圖片資源id和持續時間。例如:<?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/xxx1" android:duration="500"/>
<item android:drawable="@drawable/xxx2" android:duration="500"/>
<item android:drawable="@drawable/xxx3" android:duration="500"/>
<item android:drawable="@drawable/xxx4" android:duration="500"/>
</animation-list>
複製代碼
在XML
聲明好以後,將它做爲View的背景並經過AnimationDrawable
來播放便可。代碼以下:
mView.setBackgroundResource(R.drawable.XXX);
AnimationDrawable animationDrawable = (AnimationDrawable)mView.getBackground();
animationDrawable.start();
複製代碼
A2:經過Java代碼動態建立
//和上述xml定義方法的效果相同
AnimationDrawable ad = new AnimationDrawable();//1.建立AnimationDrawable對象
for (int i = 0; i < 4; i++) {//2.添加Drawable對象及其持續時間
Drawable drawable = getResources().getDrawable(getResources().getIdentifier("xxx" + i, "drawable", getPackageName()));
ad.addFrame(drawable, 500);
}
ad.setOneShot(false);//3.設置是否執行一次
mView.setBackgroundResource(ad);//4.將幀動畫做爲view背景
ad.start();//5.播放動畫
複製代碼
注意:使用幀動畫要注意不能使用尺寸過大的圖片,不然容易形成
OOM
( 內存溢出)錯誤想要更進一步瞭解幀動畫的讀者,能夠看一下這篇文章:關於 逐幀動畫 的使用都在這裏了!
用途:屬性動畫中的插值器和估值器能夠實現非勻速動畫
Interpolator
)做用:根據時間流逝的百分比計算出當前屬性值改變的百分比。肯定了動畫效果變化的模式,如勻速變化、加速變化、減速變化等等。
經常使用的系統內置插值器:
a.線性插值器(LinearInterpolator
):勻速動畫
b.加速減速插值器(AccelerateDecelerateInterpolator
):動畫兩頭慢中間快
c.減速插值器(DecelerateInterpolator
):動畫愈來愈慢
可針對的對象:
a.View動畫:插值器對應的屬性是android:interpolator
b.屬性動畫:是實現非勻速動畫的重要手段。
自定義插值器方法:實現 Interpolator
/ TimeInterpolator
接口 ,而後複寫getInterpolation()
- 補間動畫實現
Interpolator
接口、屬性動畫實現TimeInterpolator
接口。TimeInterpolator
接口是屬性動畫中新增的,用於兼容Interpolator
接口。
TypeEvaluator
)
- 整型估值器(
IntEvaluator
)- 浮點型估值器(
FloatEvaluator
)- Color屬性估值器(
ArgbEvaluator
)
TypeEvaluator
接口,而後複寫evaluate()
。限於篇幅,本篇文章未介紹自定義插值器和估值器的實例,想要了解的讀者,能夠看下這篇文章:
View動畫 | 屬性動畫 | |
---|---|---|
實現方式 | 經過不斷圖形變換 | 經過動態改變對象屬性 |
做用對象 | View | 任何對象,甚至沒有對象 |
存放位置 | anim | animator |
狀態變化 | 未真正改變View位置 | 真正改變View位置 |
XML
在
res/animator/
下可建立屬性動畫的XML
文件。其中,根節點set
對應AnimatorSet
類,子節點objectAnimator
對應ObjectAnimator
類、animator
對應ValueAnimator
類。經常使用屬性:
//animator/XX.xml
<set android:ordering=["together" | "sequentially"]>
<objectAnimator android:propertyName="string" android:duration="int" android:valueFrom="float | int | color" android:valueTo="float | int | color" android:startOffset="int" android:repeatCount="int" android:repeatMode=["repeat" | "reverse"] android:valueType=["intType" | "floatType"]/>
<animator android:duration="int" android:valueFrom="float | int | color" android:valueTo="float | int | color" android:startOffset="int" android:repeatCount="int" android:repeatMode=["repeat" | "reverse"] android:valueType=["intType" | "floatType"]/>
<set>
...
</set>
</set>
//java
AnimatorSet set= AnimatorInflater.loadAnimator(myContext,R.anim.xxx);
set.setTarget(mBtn);
set.start();
複製代碼
首先介紹set
標籤下的經常使用屬性:
ordering
:設置動畫的時序關係。可選值:
- together:默認值。表示動畫集合中的子動畫同時播放
- equentially:表示動畫集合中的子動畫按照書寫的前後順序依次播放
接下來具體介紹屬性動畫的實現方式:
A.經過ObjectAnimator實現屬性動畫
object
)的屬性值進行改變操做,從而實現動畫效果。objectAnimator
propertyName
:屬性動畫做用的屬性名稱
duration
: 動畫持續時長
startOffset
:設置動畫執行以前的等待時長
repeatCount
:動畫重複執行的次數;默認爲0,表示只播放一次。設置爲**-1或infinite**,表示無限重複。
repeatMode
:動畫重複執行的模式。可選值:a.
restart
:表示連續重複,爲默認值。b.
reverse
:表示逆向重複
valueFrom
:動畫初始值
valueTo
:動畫結束值
valueType
:表示propertyName
指定的屬性值類型。可選值:a.
intType
:以上兩個value
屬性值爲整型。b.
floatType
:即以上兩個value
屬性值爲浮點型,爲默認值。c.
color
:若propertyName
爲color
,則無需設置該屬性。
B.經過ValueAnimator實現屬性動畫
ObjectAnimator
與ValueAnimator
類的區別:
- ValueAnimator 類是先改變值,而後手動賦值給對象的屬性從而實現動畫;是間接對對象屬性進行操做
- ObjectAnimator 類是先改變值,而後自動賦值給對象的屬性從而實現動畫;是直接對對象屬性進行操做
animator
objectAnimator
標籤少一個android:propertyName
屬性,其餘相同JAVA
實際開發中建議用
JAVA
的方式來實現屬性動畫,緣由:
- 經過代碼來實現比較簡單
- 不少時候屬性的起始值沒法提早肯定
A.ObjectAnimator
注意:這裏
ObjectAnimator
做用的屬性必須有set
方法(
get
方法可選;當動畫沒有設置初始值的時候,get
必須存在)
//第一個參數是對象,第二個是對象的屬性名字,第3個是值的變化,能夠是ofFloat或者是ofInt,根據參數的類型直接寫
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);
//設置持續時間
objectAnimator.setDuration(2000);
objectAnimator.start();
複製代碼
//ofFloat直接返還一個 ObjectAnimator對象
public static ObjectAnimator ofFloat (Object target,String propertyName,float... values){
ObjectAnimator anim=new ObjectAnimator (target,propertyName);
anim.setFloatValues(values);
return anim;
}
複製代碼
B.ValueAnimator
ValueAnimator
不提供任何動畫效果,更像一個數值發生器,用來產生有必定規律的數字,從而讓調用者控制動畫的實現過程。- 通常在
AnimatorUpdateListener
/AnimatorListenerAdapter
(在下文會詳細介紹)中監聽數值的變化,而完成動畫的變換
測試實例:
//實現顏色的漸變
ValueAnimator valueAnimator = ValueAnimator.ofArgb(0xFFFF5454, 0xFF5DDE5D, 0xFF5DBEDE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int color = (int) animation.getAnimatedValue();
button.setBackgroundColor(color);
}
});
valueAnimator.setDuration(2000);
//記得start
valueAnimator.start();
複製代碼
C.組合動畫
C1.AnimatorSet
能夠實現有前後順序的組合動畫
play:傳入一個
Animator
對象 ,會返回一個AnimatorSet.Builder
的實例Builder中有4個方法:
a.
after(Animator)
:將現有動畫插入到傳入的動畫以後執行b.
before(Animator)
:將現有動畫插入到傳入的動畫以前執行c.
with(Animator)
:將現有動畫和傳入的動畫同時執行。d.
after(Long)
:將現有動畫延遲指定毫秒後執行。
ObjectAnimator alphaAnimator =ObjectAnimator.ofFloat(tv, "alpha", 1, 0, 1);
ObjectAnimator rotateAnimator =ObjectAnimator.ofFloat(tv, "rotation", 0, 360, 0);
rotateAnimator.setDuration(15000);
ObjectAnimator scaleAnimator =ObjectAnimator.ofFloat(tv, "scaleX", 1, 2, 1);
ObjectAnimator translateAnimator =ObjectAnimator.ofFloat(tv, "translationX", 0, 100, 0);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(alphaAnimator)
.with(rotateAnimator)
.after(scaleAnimator)
.before(translateAnimator);
animatorSet.setDuration(2000).start();
複製代碼
C2:PropertyValuesHolder
能夠實現同時執行的組合動畫
//新建動畫類
PropertyValuesHolder valuesHolder1=PropertyValuesHolder.ofFloat("scaleX",1.0f,1.5f);
PropertyValuesHolder valuesHolder2=PropertyValuesHolder.ofFloat("rotationX",0f,90.0f);
//新建ObjectAnimator
ObjectAnimator animator=ObjectAnimator.ofPropertyValuesHolder(view,valuesHolder1,valuesHolder2);
//開啓動畫
animator.setDuration(200).start();
複製代碼
屬性動畫主要使用兩個接口:
AnimatorUpdateListener
&AnimatorListener
來監聽動畫的播放過程。
AnimatorListener
:監聽動畫的開始、結束、取消以及重複播放。以下:public static interface AnimatorListener {
void onAnimationStart(Animator animation); //動畫開始
void onAnimationEnd(Animator animation); //動畫結束
void onAnimationCancel(Animator animation); //動畫取消
void onAnimationRepeat(Animator animation); //動畫重複播放
}
複製代碼
爲方便開發,系統提供了
AnimatorListenerAdapter
類,它是AnimatorListener
的適配器,如此可有選擇複寫上述四個方法。
AnimatorUpdateListener
:監聽整個動畫過程。每播放一幀,onAnimationUpdate()
就會被調用一次,以下:public interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator var1);//在屬性動畫的屬性值變化是回調。
}
複製代碼
- 對象必須提供
set
方法,若未傳遞初始值給動畫,還需提供get
方法(由於系統須要去取初始值)set
方法對屬性所作的改變必須能經過某種方式反映出來(例如:UI效果改變)
解決方法:
A.給對象加上get
和set
方法
這個方法通常不可行,由於大多數的時候,咱們沒有權限
B.用包裝類的方式,間接提供get
和set
方法
實例:
class MyView{
private View mTarget;
private MyView (View view){
mTarget =view;
}
//屬性的get方法
public int getWidth(){
return mTarget.getLayoutParams().width;
}
//屬性的set方法
public void setWidth(int width){
mTarget.getLayoutParams().width=width;
mTarget.requestLayout();
}
}
複製代碼
MyView myView = new MyView(mButton);
ObjectAnimator.ofInt(myView, "width", 500).setDuration(500).start();
複製代碼
C.用ValueAnimator
監聽動畫過程,本身改變屬性
測試實例:
/** * 改變對象的寬度 * @param target 對象 * @param start 起始值 * @param end 目標值 */
private void performAnimate(final View target, final int start, final int end) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//持有一個IntEvaluator對象,方便下面估值的時候使用
IntEvaluator evaluator = new IntEvaluator();
//獲得當前動畫的進度值
float fraction = animation.getAnimatedFraction();
//調用整型估值器,經過比例計算出寬度,而後設給Btn
target.getLayoutParams().width = evaluator.evaluate(fraction, start, end);
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}
複製代碼
具體體如今 :
- 建立屬性動畫時,若未設初值,則系統會經過該屬性的
get()
方法獲取初始值。故屬性動畫要求必須提供屬性的get()
方法- 在動畫播放的過程當中,利用時間插值器和類型估值器獲取改變後的屬性值
- 將改變後的屬性值經過
set()
方法設置到對象中。故屬性動畫要求必須提供屬性的set()
方法
get/set
方法是經過反射調用的,筆者將帶你深刻屬性動畫的源碼,探究其緣由:
恭喜你!已經看完了前面的文章,相信你對
Animation
已經有必定深度的瞭解!在使用過程當中,也有一些事項是須要咱們注意的:
這個問題主要出如今幀動畫中,當圖片數量較多且圖片較大時易出現OOM,因此平常開發中儘可能避免使用幀動畫
- 屬性動畫中有一類無限循環的動畫(
repeatCount=-1
),這類動畫須要在Activity
退出時及時中止,不然致使Activity
沒法釋放形成內存泄漏View
動畫不存在這個問題
View動畫是對View的影像作動畫,不是真正改變View的狀態,有時候出現動畫完成後View沒法隱藏的現象(
setVisibility(View.GONE)
失效),須要調用view.clearAnimation()
清除View動畫
在進行動畫的過程當中,儘可能使用dp,使用px會致使在不一樣的設備上有不一樣的效果
想要了解具體緣由的讀者,筆者給您推薦一篇文章:dp、sp、px區別
Android3.0
以後,屬性動畫的單擊事件觸發位置爲移動後的位置,可是View
動畫仍在原位置
Android4.0
開始默認開啓硬件加速
若是文章對您有一點幫助的話,但願您能點一下贊,您的點贊,是我前進的動力
本文參考連接: