LayoutTransition 佈局動畫筆記

LayoutTransition可以實現在ViewGroup組件內部佈局結構發生變化的時候,產生一定的動畫效果,以免佈局切換的時候視覺上很生硬。

首先需要調用ViewGroup.setLayoutTransition(LayoutTransition),這樣無論ViewGroup容器添加或移除子視圖的時候,都會產生布局變動的動畫效果;

如果希望指定自定義的動畫效果,使用LayoutTransition.setAnimator()方法;


佈局屬性動畫一共有五種類型:
APPEARING    :   視圖出現
DISAPPEARING   :  視圖消失
CHANGE_APPEARING      : 視圖出現時,其他組件產生變化
CHANGE_DISAPPEARING :  視圖消失時,其他組件產生變化
CHANGING : 非添加和移除組件產生布局變化時,觸發的佈局
其中前4種是自定義屬性動畫常用的。

佈局屬性動畫觸發條件: 有視圖組件被添加進容器或從容器中消失,注:消失是指Gone,如果是Invisible,不會觸發佈局屬性動畫;

佈局屬性動畫的執行時序:
DISAPPEARING 動畫是立即執行的,
CHANGE_APPEARING ,動畫是立即執行的
APPEARING 動畫在CHANGE_APPEARING 完成之後執行;
CHANGE_DISAPPEARING 動畫在DISAPPEARING 完成之後執行

    添加組件的時候,需要其他組件給待添加組件騰出空間,所以其他組件先移動,空間具備後,待添加的組件執行出現時候的動畫效果;移除時順序反之;
如果希望自己控制這四種動畫的執行時間,可以通過LayoutTransition.setDuration(int, long) 和LayoutTransition.setStartDelay(int, long)來手動控制

通過xml佈局文件也可以實現簡單通用的佈局屬性動畫,在ViewGroup組件下面設置屬性:
    animateLayoutChanges="true"
如果佈局的嵌套結構比較複雜的話,這種方式可能會失效;官方的解釋爲複雜佈局在佈局變化的時候,組件的位置計算可能會出現不一致。
 Using LayoutTransition at multiple levels of a nested view hierarchy may not work due to the interrelationship of the various levels of layout. Also, a container that is being scrolled at the same time as items are being added or removed is probably not a good candidate for this utility, because the before/after locations calculated by LayoutTransition may not match the actual locations when the animations finish due to the container being scrolled as the animations are running

實例:

/**
* view出現時 繞自身Y軸旋轉半周
*/
ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 90F, 0F).
setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);

/**
* view 消失時,繞自身X軸旋轉半周
*/
ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "rotationX", 0F, 90F).
setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animator2);

/**
* view 動畫改變時,佈局中的每個子view動畫的時間間隔
*/
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);

/**
* 爲什麼這裏要這麼寫?具體我也不清楚,ViewGroup源碼裏面是這麼寫的,我只是模仿而已
* 不這麼寫貌似就沒有動畫效果了,所以你懂的!
* 參數具體設什麼值好像沒什麼影響,但是在ObjectAnimator中必須要指定這4個屬性變化範圍
*/
PropertyValuesHolder pvhLeft =
PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop =
PropertyValuesHolder.ofInt("top", 0, 1);
PropertyValuesHolder pvhRight =
PropertyValuesHolder.ofInt("right", 0, 1);
PropertyValuesHolder pvhBottom =
PropertyValuesHolder.ofInt("bottom", 0, 1);
/**
* view出現時,導致整個佈局改變的動畫
* 後面三參數表示,動畫從第一個參數變化到第二個參數,最終到3三個參數
*/
PropertyValuesHolder animator3 = PropertyValuesHolder.ofFloat("scaleX", 1F, 2F, 1F);
PropertyValuesHolder animator4 = PropertyValuesHolder.ofFloat("scaleY", 1F, 2F, 1F);
final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom,animator3,animator4).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
changeIn.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
view.setScaleX(1.0f);
}
});
mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);

/**
* view消失,導致整個佈局改變時的動畫
* 幀屬性動畫,幀代表相對Duration這個週期的相對瞬間,0.5f表示Duration/2時間
*/
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 2f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation =
PropertyValuesHolder.ofKeyframe("scaleX", kf0, kf1, kf2);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
changeOut.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
view.setScaleX(1.0f);
}
});
mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章