一.屬性動畫補充
1.屬性動畫補充-為不具有get/set方法的屬性提供修改方法
在前一篇文章講到ObjectAnimator對View的屬性進行動畫,該屬性需要在view有set/get方法,但是對不具有get/set方法的屬性該如何進行動畫:
Google在應用層為我們提供了2種解決方法,一種是通過自己寫一個包裝類,來為該屬性提供get/set方法,還有一種是通過ValueAnimator來實現,ValueAnimator的方法我們在下面會具體講解,這里講解下如何使用自定義的包裝類來給屬性提供get/set方法。
包裝類
private static class WrapperView {
private View mTarget;
public WrapperView(View target) {
mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
使用方法
WrapperView wrapper = new WrapperView (mButton);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
這樣就間接給他加上了get/set方法,從而可以修改其屬性實現動畫效果。
2.多動畫效果的另一種實現方法——propertyValuesHolder
public void propertyValuesHolder(View view) {
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,
0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,
0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ)
.setDuration(1000).start();
}
3.KeyFrame
keyFrame是一個 時間/值 對,通過它可以定義一個在特定時間的特定狀態,即關鍵幀,而且在兩個keyFrame之間可以定義不同的Interpolator,就好像多個動畫的拼接,第一個動畫的結束點是第二個動畫的開始點。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當的KeyFrame,然后通過PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對象,
有如下案例:
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
rotationAnim.setDuration(2000);
分析:上述代碼的意思為:設置btn對象的width屬性值使其:
開始時 Width=400,動畫開始1/4時 Width=200,動畫開始1/2時 Width=400,動畫開始3/4時 Width=100,動畫結束時 Width=500
第一個參數為時間百分比,第二個參數是在第一個參數的時間時的屬性值。
定義了一些Keyframe后,通過PropertyValuesHolder類的方法ofKeyframe一個PropertyValuesHolder對象,然后通過ObjectAnimator.ofPropertyValuesHolder獲得一個Animator對象。
上述代碼也可替換為(上述代碼時間值是線性,變化均勻):
ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);
oa.setDuration(2000);
oa.start();
4.View的animate方法
3.0后android對View也提供了直接作用的動畫API:
view.animate().alpha(0).y(100).setDuration(1000)
.withStartAction(new Runnable() {
@Override
public void run() {
}
}).withEndAction(new Runnable() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
}).start();
二.布局動畫 - ViewGroup在布局時產生的動畫效果
1.LayoutTransition
通過LayoutTransition來實現容器在添加子view的時候的動畫過渡效果:
過渡的類型一共有四種:
- LayoutTransition.APPEARING 當一個View在ViewGroup中出現時,對此View設置的動畫
- LayoutTransition.CHANGE_APPEARING當一個View在ViewGroup中出現時,對此View對其他View位置造成影響,對其他View設置的動畫
- LayoutTransition.DISAPPEARING當一個View在ViewGroup中消失時,對此View設置的動畫
- LayoutTransition.CHANGE_DISAPPEARING當一個View在ViewGroup中消失時,對此View對其他View位置造成影響,對其他View設置的動畫
- LayoutTransition.CHANGE 不是由于View出現或消失造成對其他View位置造成影響,然后對其他View設置的動畫。
注意動畫到底設置在誰身上,此View還是其他View。
2.AnimateLayoutChanges動畫
ViewGroup的xml屬性中有一個默認的animateLayoutChanges屬性,設置該屬性,可以添加ViewGroup增加view的過渡效果:
<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="add"
android:text="Add Button"/>
</LinearLayout>
3.LayoutAnimation動畫
通過設置LayoutAnimation也同樣可以實現布局動畫效果
public class AnimateLayoutAnimation extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animate_layout_animation);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
sa.setDuration(2000);
// 第二個參數dely : the delay by which each child's animation must be offset
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);
// 設置顯示的順序 這個必須要在dely不為0的時候才有效
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
ll.setLayoutAnimation(lac);
}
}