Android animation translate toYDelta XML位移结束Y值

2次阅读

xml动画中 translatey 对应 android:toydelta 属性,表示相对于原始位置的y轴偏移量,单位支持 px、%(自身高度)、%p(父容器高度),需与 android:fromydelta 配对使用。

Android animation translate toYDelta XML位移结束Y值

translateY 在 XML 动画里到底用哪个属性?

XML 中没有 toYDelta 这个属性,这是常见误解的源头。Android 的 translate 动画(Translateanimation)早已被弃用,而现代 XML 动画(`` / ``)只支持 android:fromYDeltaandroid:toYDelta ——注意是 toYDelta,不是 toYtoYValue

它表示「相对于自身原始位置的 Y 方向偏移量」,单位是像素(px)或百分比(%、%p),不是绝对坐标。

  • android:toYDelta="100":向下移动 100 像素
  • android:toYDelta="50%":向下移动自身高度的 50%
  • android:toYDelta="-25%p":向上移动父容器高度的 25%

为什么设了 toYDelta 却没动?

最常见原因是动画未正确应用到 View,或动画本身被覆盖/中断。XML 动画默认不自动播放,且 android:toYDelta 必须和 android:fromYDelta 配对使用(哪怕值相同),否则行为不可靠。

  • 忘记调用 view.startAnimation(),或用了过时的 AnimationUtils.loadAnimation() 加载后没 attach
  • 在 ConstraintLayout 中,如果 View 有垂直约束(如 app:layout_constraintTop_toTopOf),位移动画可能被布局重绘“拉回原位”
  • 同时设置了 android:fillAfter="true" 但没配 android:fillEnabled="true",导致结束位置不保留
  • 目标 View 的 visibilitygone —— gone 的 View 不参与绘制,动画无效

替代方案:用 ViewPropertyAnimator 更稳

XML translate 动画本质是修改绘制层的矩阵,不改变 View 的实际 layout 参数,所以点击区域、测量尺寸都不变。真要让 View “真正移到新位置”,得用属性动画:

  • view.animate().translationY(200f).duration(300):单位是像素(Float),直接设最终 Y 偏移量
  • 搭配 .withEndAction() 可在动画结束后手动更新 LayoutParams,实现真实位移
  • 注意:translationY 是相对自身原始 top 的偏移,和 XML 的 toYDelta 语义一致,但更可控、可中断、可组合
  • 如果需要兼容旧 API,别用 ObjectAnimator.ofFloat(view, "y", ...) ——它改的是绝对坐标,会和 translationX/Y 冲突

单位混用导致位移错乱

toYDelta 支持三种单位,但混合使用极易出错:

  • 纯数字(如 120)= px,跟屏幕密度强相关,不同设备表现不一致
  • 50% = 相对于自身高度的百分比,50%p = 相对于父容器高度的百分比 —— 少一个 p 结果差十倍
  • res/anim/ 下写 50dp 是非法的,XML 动画不解析 dp/sp,会直接报 Resources$NotFoundException
  • 推荐统一用 %p 做响应式位移(比如从底部弹入: fromYDelta="100%p", toYDelta="0"

复杂点在于:XML 动画的 Delta 是叠加在当前 translation 状态上的,如果之前用代码调过 setTranslationY(),再播 XML 动画,起始位置就不是原始位置了 —— 这个叠加逻辑常被忽略。

text=ZqhQzanResources