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

translateY 在 XML 动画里到底用哪个属性?
XML 中没有 toYDelta 这个属性,这是常见误解的源头。Android 的 translate 动画(TranslateAnimation)早已被弃用,而现代 XML 动画(`android:fromYDelta 和 android:toYDelta ——注意是 toYDelta,不是 toY 或 toYValue。
它表示「相对于自身原始位置的 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 的
visibility是gone——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 动画,起始位置就不是原始位置了 —— 这个叠加逻辑常被忽略。










