LayoutTransition 布局动画笔记

本文介绍了如何利用LayoutTransition在ViewGroup中实现布局变化时的动画效果,包括设置布局动画、五种动画类型及其触发条件、执行时序。同时展示了如何自定义动画效果,并通过实例演示了视图出现和消失时的不同动画操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值