上一篇
安卓开发动画移动效果
- 行业动态
- 2025-04-22
- 5
安卓动画移动效果实现指南
动画类型与适用场景
动画类型 | 适用场景 |
---|---|
View Animation | 简单平移/缩放/旋转,兼容性好(API 11+),但无法保存状态 |
Property Animation | 复杂属性变化,可保存最终状态,支持ObjectAnimator/ValueAnimator |
Jetpack Animator | 兼容低版本,提供预定义动画模板(如淡入淡出、滑动) |
Transition | 场景切换动画(如Activity/Fragment跳转时的共享元素动画) |
核心实现步骤
View Animation(补间动画)
<!-res/anim/move.xml --> <translate android:fromXDelta="0" android:toXDelta="200dp" android:duration="300"/>
val animation = AnimationUtils.loadAnimation(context, R.anim.move) imageView.startAnimation(animation)
Property Animation(属性动画)
// 移动View到(300,500)位置 ObjectAnimator.ofFloat(view, "translationX", "translationY") .setFloatValues(0f, 300f, 0f, 500f) .setDuration(500) .start()
Jetpack Animator
// 使用扩展函数实现滑动进入 val slideProvider = Slide(Gravity.START) AnimatorInflater.loadAnimator(context, R.animator.slide_in) .setTarget(view) .start()
关键参数控制
参数 | 作用 | 示例值 |
---|---|---|
duration | 动画时长 | 300(毫秒) |
interpolator | 速度控制曲线 | AccelerateDecelerateInterpolator |
repeatCount | 重复次数(-1为无限循环) | 0(不重复) |
fillAfter | 动画结束后保持状态 | true/false |
常见问题处理
动画结束后视图回弹
- 原因:未设置
fillAfter=true
或未正确处理最终状态 - 解决方案:
animation.fillAfter = true // XML中设置 // 或通过监听器固定位置 animation.setAnimationListener(object : Animation.AnimationListener { override onAnimationEnd(animation) { view.x = 200f // 手动设置最终坐标 } })
复杂路径移动
- 方案:使用
PathInterpolator
或自定义TypeEvaluator
- 示例:沿贝塞尔曲线移动
val path = Path().apply { moveTo(0f, 0f) cubicTo(100f, -50f, 200f, 300f, 300f, 0f) } ObjectAnimator.ofObject(view, "x", "y", PathInterpolator(path), 0f, 1f) .setDuration(1000) .start()
性能优化建议
- 硬件加速:启用
android:hardwareAccelerated="true"
- 减少视图层级:动画过程中避免频繁调用
invalidate()
- 复用动画对象:预先创建动画实例,避免重复加载资源
- 列表动画优化:使用
RecyclerView.ItemAnimator
代替全局动画
相关问题与解答
Q1:如何让属性动画更流畅?
A1:
- 使用
TimeInterpolator
优化速度曲线(如DecelerateInterpolator
模拟自然减速) - 开启硬件加速:
view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
- 降低动画频率:对60fps设备,单帧耗时不超过16ms
- 避免在动画回调中执行复杂计算
Q2:在RecyclerView中如何实现item移动动画?
A2:
- 自定义
RecyclerView.ItemAnimator
:class MoveAnimator : SimpleItemAnimator() { override fun animateMove(...) { val anim = ObjectAnimator.ofFloat(view, "translationX", startX, endX) anim.duration = 300 anim.start() } } recyclerView.itemAnimator = MoveAnimator()
- 使用
DiffUtil
配合ListAdapter
自动计算位移 - 对长列表启用
itemViewCacheSize
缓存