1、概述
首先。什么是布局动画。就是ViewGroup在布局时产生的动画。(不仅仅局限于添加View,也包括删除View或者导致位置变化等一系列原因,我们都可以认为是布局动画)
2、LayoutTransition动画
通过LayoutTransition,我们可以实现ViewGroup在添加子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设置的动画。
public class AnimateLayoutTransition extends Activity {
private LinearLayout ll;
private LayoutTransition mTransition = new LayoutTransition();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animate_layout_transition);
ll = (LinearLayout) findViewById(R.id.ll);
setupCustomAnimations();
ll.setLayoutTransition(mTransition);
}
public void add(View view) {
final Button button = new Button(this);
ll.addView(button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
ll.removeView(button);
}
});
}
// 生成自定义动画
private void setupCustomAnimations() {
// 动画:CHANGE_APPEARING
// 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(
mTransition.getDuration(LayoutTransition.CHANGE_APPEARING));
mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
changeIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
// View也支持此种动画执行方式了
view.setScaleX(1f);
view.setScaleY(1f);
}
});
// 动画:CHANGE_DISAPPEARING
// 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(
mTransition
.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
mTransition
.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
changeOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotation(0f);
}
});
// 动画:APPEARING
// Adding
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,
0f).setDuration(
mTransition.getDuration(LayoutTransition.APPEARING));
mTransition.setAnimator(LayoutTransition.APPEARING, animIn);
animIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationY(0f);
}
});
// 动画:DISAPPEARING
// Removing
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f,
90f).setDuration(
mTransition.getDuration(LayoutTransition.DISAPPEARING));
mTransition.setAnimator(LayoutTransition.DISAPPEARING, animOut);
animOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationX(0f);
}
});
}
}