private void resetTransition() {
mTransitioner = new LayoutTransition();
levelOkLayout.setLayoutTransition(mTransitioner);
}
private void initAnim(){
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);
setupCustomAnimations();
long duration;
duration = 500;
mTransitioner.setDuration(duration);
}
//設置自定義動畫的方法
private void setupCustomAnimations() {
// Changing while Adding
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);
PropertyValuesHolder pvhScaleX =
PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
PropertyValuesHolder pvhScaleY =
PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX, pvhScaleY).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
changeIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setScaleX(1f);
view.setScaleY(1f);
}
});
// Changing while Removing
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation =
PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
changeOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotation(0f);
}
});
// Adding
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f, 0f).
setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
mTransitioner.setAnimator(LayoutTransition.APPEARING, animIn);
animIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationY(0f);
}
});
// Removing
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f).
setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);
animOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationX(0f);
}
});
}
使用LayoutTransition類在ViewGroup內部處理佈局變化的動畫。當調用一個View對象的setVisibility()方法,或者設置該View的GONE常量,或者把該View對象添加到ViewGroup中(或者從ViewGroup中刪除)時,在ViewGroup內部的View對象就能夠實現時隱時現的動畫效果。當在ViewGroup對象中添加或刪除View對象時,其中的其他View對象也能夠動畫移動到新的位置。在LayoutTransition對象內通過調用setAnimator()方法,並且在傳遞給該方法的Animator對象參數中帶有下列LayoutTransition常量之一,就能夠定義該常量所代表的動畫:
1. APPEARING---一個標記,它指示要在容器中正在顯示的項目上運行動畫;
2. CHANGE APPEARING---一個標記,它指示在容器中由於新項目的出現而導致其他項目變化所要運行的動畫;
3. DISAPPEARING---一個標記,它指示一個從容器中消失的項目所要運行的動畫;
4. CHANGE_DISAPPEARING---一個標記,它指示由於一個項目要從容器中消失而導致其他項目的變化,所要運行的動畫。
能夠給這四種事件類型定義自定義動畫,以便定製自己的佈局過渡效果,也可以告訴動畫系統只使用默認的動畫效果。
在APIDemo中的LayoutAnimations示例,顯示瞭如何給佈局的過渡定義動畫效果,並且在想要動畫效果的View對象上設置動畫。
LayoutAnimationsByDefault類以及它對應的layout_animations_by_default.xml佈局資源文件顯示瞭如何在XML中啓用ViewGroup對象的默認佈局過渡效果。需要做的事情僅僅是把ViewGroup元素的android.animateLayoutchanges屬性設置爲true。例如:
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
android:animateLayoutChanges="true" />
如果把這個屬性設置爲true,那麼在該ViewGroup對象中添加或刪除View對象,以及ViewGroup對象中其他的View對象都會自動的具有動畫效果。
使用TypeEvaluator www.2cto.com
如果想要的動畫類型是Android系統所未知的,那麼通過實現TypeEvaluator接口就能夠創建自己的評價器。Android系統已知的類型是int、float或顏色(color),分別有IntEvaluator、FloatEvaluator和ArgbEvaluator類型的評價器所支持。
在TypeEvaluator接口中只有一個要實現的方法:evaluate()方法。這個方法允許正在使用的動畫處理器返回一個適用於於當前動畫時點動畫屬性值,FloatEvaluator類演示了這個方法是如何做這件事的:
public class FloatEvaluator implements TypeEvaluator {
public Object evaluate(float fraction, Object startValue, Object endValue) {
float startFloat = ((Number) startValue).floatValue();
return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
}
}
注意:當ValueAnimator對象(或ObjectAnimator對象)運行時,它會計算當前的動畫過去因子(一個0到1之間的值),然後根據你所使用的插值類型來計算一個要插入的動畫的版本。插值因子是由TypeEvaluator對象通過fraction參數接收來的,因此在計算動畫值的時候,不需要考慮插值。