指定 ViewGroup 的子元素出场动画,作用在每个子元素上的动画是补间动画。
在 res/anim
目录创建 layout_anim.xml
文件
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.2"
android:animationOrder="normal"
android:animation="@anim/item_anim" />
其中 item_anim 是一个普通的补间动画。
属性:
然后对有子 View 的 ViewGroup 添加这个属性,比如 RecyclerView:
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutAnimation="@anim/layout_anim" />
其中子元素所用的补间动画代码方式前面已经说过,这里就直接用 xml 文件了。
val itemAnim = AnimationUtils.loadAnimation(ctx, R.anim.item_anim)
// val controller = LayoutAnimationController(itemAnim)
// controller.delay = 0.5f
val controller = LayoutAnimationController(itemAnim, 0.5f)
controller.order = LayoutAnimationController.ORDER_NORMAL
recycler.layoutAnimation = controller
在 3.0 以上版本中,如果给 ViewGroup 加上 android:animateLayoutChanges="true"
,布局变化时会自动加上默认的动画。
目前系统支持以下 5 种状态变化,可以为任意一种状态设置自定义动画:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/rootView"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btnAdd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="addView" />
<Button
android:id="@+id/btnRemove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="removeView" />
</LinearLayout>
</LinearLayout>
private var count = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_layout_transition)
// setTransitionAnimator()
btnAdd.onClick {
val view = TextView(ctx)
view.text = "Text${count++}"
view.backgroundColor = Color.GRAY
view.padding = 20
rootView.addView(view)
}
btnRemove.onClick {
if (count-- > 1) {
rootView.removeViewAt(1)
}
}
}
支持自定义动画效果
@SuppressLint("ObjectAnimatorBinding")
private fun setTransitionAnimator() {
val transition = LayoutTransition()
// 为 ViewGroup 容器绑定 LayoutTransition 对象
rootView.layoutTransition = transition
// 使用翻转进入的动画代替默认的 APPEARING 动画
val appearAnim = ObjectAnimator
.ofFloat(null, "rotationY", 90f, 0f)
.setDuration(transition.getDuration(LayoutTransition.APPEARING) * 10)
transition.setAnimator(LayoutTransition.APPEARING, appearAnim)
// 使用滑动动画代替默认布局改变的动画
// 这个动画会让视图滑动进入并短暂地缩小一半,具有平滑和缩放的效果
val pvhSlide = PropertyValuesHolder.ofFloat("y", 0f, 1f)
val pvhScaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.5f, 1f)
val pvhScaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.5f, 1f)
val changingDisappearAnim = ObjectAnimator.ofPropertyValuesHolder(this, pvhSlide, pvhScaleY, pvhScaleX)
changingDisappearAnim.duration = transition.getDuration(LayoutTransition.CHANGE_DISAPPEARING)
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changingDisappearAnim)
}
效果:
2018_03_31_18_13_43.gif