scale动画中pivotx/pivoty仅在scaleanimation(即xml中标签)生效,objectanimator或viewpropertyanimator需代码调用setpivotx/y,且单位须明确为”50%”(自身)或”50%p”(父容器),小数如”0.5″表示像素而非比例。

scale 动画里 pivotX/pivotY 不生效?先确认动画类型
XML 中 scale 动画的中心点由 pivotX 和 pivotY 控制,但它们只在 ScaleAnimation(即 scale 标签)中起作用,**不是所有缩放都认这两个属性**。比如用 ObjectAnimator 配合 scaleX/scaleY 属性时,pivot 是 View 自身的 setPivotX()/setPivotY() 决定的,XML 里的 pivotX 完全被忽略。
常见错误现象:android:pivotX="50%" 写了但动画还是从左上角缩放——大概率你用的是 ObjectAnimator 加 scaleX,不是 scale 动画。
- 用
<scale></scale>标签(继承自ScaleAnimation):支持android:pivotX、android:pivotY,单位可为像素、百分比(如"50%")或百分比父容器("50%p") - 用
<objectanimator></objectanimator>动画属性:必须在 Java/kotlin 中提前调用view.setPivotX(…)和view.setPivotY(…),XML 里写pivotX没用 - 注意兼容性:
"50%p"在 API 21+ 才支持,低版本会解析失败并 fallback 到 0
百分比 pivot 值写法不对,动画中心偏移很奇怪
XML 中 pivotX 和 pivotY 的值看似简单,但单位混用会导致行为完全不可控。比如 android:pivotX="0.5" 看起来像“一半”,其实是 **0.5 像素**,不是比例;而 android:pivotX="50%" 才是相对于自身宽高的 50%;android:pivotX="50%p" 是相对于父容器宽高的 50%。
最容易踩的坑:把小数当比例用,结果 pivot 锁死在左上角附近,缩放看起来像平移。
-
"0.5"→ 0.5 像素(几乎没效果,等同于 0) -
"50%"→ 自身宽度的 50%,适用于居中缩放自身 -
"50%p"→ 父容器宽度的 50%,适用于希望锚点随父布局变化的场景(如全屏弹窗) - 如果 View 尺寸为 0(比如刚 inflate 还没 measure),
"50%"也会计算为 0,建议确保动画触发前 View 已完成 layout
Java/Kotlin 里 setPivotX 后 XML scale 动画还是不按预期缩放
View 的 pivot 是一个状态,会被多次设置覆盖。如果你在代码里调用了 view.setPivotX(100f),又加载了 XML 中 android:pivotX="50%" 的 scale 动画,最终生效的是代码设置的值——因为 ScaleAnimation 构造时会读取当前 pivot 值,而不是 XML 声明的值。
也就是说:scale 动画的 XML 中 pivotX 只在动画初始化时被读取一次,它不会主动修改 View 的 pivot 状态,也不会覆盖你代码里设好的 pivot。
- 想让 XML 动画严格按声明的 pivot 执行:确保动画开始前,View 的 pivot 正好是你期望的值(比如先
view.setPivotX(view.getWidth() * 0.5f)) - 如果用
AnimationUtils.loadAnimation()加载 XML,它不会重置 pivot,只读取当前值 - 调试技巧:动画开始前打日志
Log.d("Pivot", "x=" + view.getPivotX() + ", y=" + view.getPivotY()),确认是否和预期一致
API 21+ 用 ViewPropertyAnimator 做 scale,pivot 必须提前设且不能动
用 view.animate().scaleX(0.5f).scaleY(0.5f) 这类链式调用时,pivot 完全由 View 当前的 getPivotX()/getPivotY() 决定,而且一旦动画开始,再改 pivot 不会影响正在进行的动画。
这时候 XML 已经完全无关了,所有控制逻辑都在代码里,容易误以为“XML 没生效”,其实是根本没走 XML 路径。
- 必须在调用
.animate()之前设置 pivot,例如:view.setPivotX(view.getWidth() / 2f); view.setPivotY(view.getHeight() / 2f); - 如果 View 尺寸还没确定(比如在
onCreate()里直接设),用ViewTreeObserver等待 layout 完成后再设 pivot - 注意:
ViewPropertyAnimator的 scale 是硬件加速的,pivot 改变后若未触发重绘,可能视觉上卡顿或错位
动画中心点这事,表面就两个属性,实际牵扯到动画类型、View 状态时机、单位语义、API 兼容性四层判断。漏掉任何一层,都会发现“明明写了 pivot 却不按想的动”。