Material-Animations ArcMotion 实战指南:几行 XML 让共享元素动画走出弧线轨迹
【免费下载链接】Material-AnimationsAndroid Transition animations explanation with examples.项目地址: https://gitcode.com/gh_mirrors/ma/Material-Animations
Material-Animations 是一个讲解 Android Transition 过渡动画框架的开源示例项目,涵盖 Activity 切换过渡、共享元素过渡(Shared Element Transition)和布局场景动画三大类效果。本篇聚焦其中一个最"高级感"的技巧:用短短几行 XML,让共享元素在两个页面之间沿弧线(ArcMotion)而非直线移动。默认情况下 ChangeBounds 过渡是直线位移,加入 ArcMotion 后轨迹会自然弯曲,更接近 Material Design 的抛物线手势感,而改动量几乎可以忽略不计。
什么是 ArcMotion:一句话讲清
ArcMotion是 Android 过渡框架内置的"弧线运动"组件,可以嵌套在 ChangeBounds、Slide 等过渡内部使用。它的作用只有一个:把原本直线的视图位移改造成一段圆弧轨迹。你通过三个属性控制弧线:
maximumAngle:最大偏转角度(弧线最弯能弯到什么程度)minimumHorizontalAngle:水平位移达到该角度比例后强制启用弧线minimumVerticalAngle:垂直位移达到该角度比例后强制启用弧线
下面这张图就是共享元素过渡的基本原理:两个 Activity 中各有一个视图通过相同的transitionName关联起来,框架自动补间位移与缩放,中间的虚线就是视图移动的轨迹——而 ArcMotion 改变的正是这条轨迹的形状。
核心:一份只有 10 行的 ArcMotion XML
整个弧线效果的全部秘密都在这份过渡资源文件里,位于 changebounds_with_arcmotion.xml:
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:duration="@integer/anim_duration_long" android:interpolator="@android:interpolator/decelerate_cubic"> <changeBounds> <arcMotion android:maximumAngle="90" android:minimumHorizontalAngle="90" android:minimumVerticalAngle="0" /> </changeBounds> </transitionSet>逐行解读这份 Android ArcMotion 弧线配置:
| 属性 | 含义 | 调参建议 |
|---|---|---|
android:duration | 过渡总时长 | 用资源引用统一管理,便于全局调整 |
android:interpolator | 时间插值器 | decelerate_cubic先快后慢,最贴合"甩出-落定"的手势感 |
maximumAngle="90" | 弧线最大角度 | 值越大弧线越弯,一般 30~90 之间 |
minimumHorizontalAngle="90" | 水平方向强制走弧线的阈值 | 保证横向位移一定出弧线 |
minimumVerticalAngle="0" | 垂直方向强制走弧线的阈值 | 设为 0 表示垂直位移也始终带弧度 |
两个关键理解:
- ArcMotion 是 changeBounds 的"子节点"——它不是独立过渡,而是挂载在 ChangeBounds 内部,只负责改写位移路径,其余逻辑(缩放、圆角渐变等)仍由 ChangeBounds 处理。
- 文件里还留了一行注释掉的
patternPathMotion,那是另一种指定"任意自定义路径"的方式;日常场景用 ArcMotion 的自动弧线就足够了。
三步接入:从直线到弧线的最短路径
第 1 步:开启窗口内容过渡
在 values/styles.xml 的主题中加入一行,全局生效:
<item name="android:windowContentTransitions">true</item>第 2 步:给源/目标视图起同一个 transitionName
两个页面中的视图可以 id、尺寸完全不同,只要android:transitionName一致,Transition 框架就会把它们视为"同一个元素"。
第 3 步:inflate 这份 XML 并设为共享元素过渡
项目的 RevealActivity.java 给出了完整用法,核心只有两行:
Transition transition = TransitionInflater.from(this) .inflateTransition(R.transition.changebounds_with_arcmotion); getWindow().setSharedElementEnterTransition(transition);启动 Activity 时再通过ActivityOptions.makeSceneTransitionAnimation()传入共享视图,弧线过渡即刻生效。同一份 XML 也可以用在同一页面内的布局变化上(配合TransitionManager.beginDelayedTransition),见 RevealActivity.java 中revealRed()的用法——红方块从按钮位置弧线飞回屏幕中央,再触发 Circular Reveal 变色,就是这套组合拳的典型效果。
为什么返回值动画也要考虑轨迹
返回时走的是 Return/Reenter 过渡,如下图所示。如果你只设置了 Enter 过渡,返回时框架会默认执行其反向动画,弧线轨迹会自动对称回来;若想返回时干脆换一种风格(例如项目里的 RevealActivity 用了一个延迟执行的Fade作为返回过渡),则单独设置returnTransition即可。
避坑清单:新手最容易踩的 4 个坑
- 忘了
windowContentTransitions:不加这行,共享元素过渡完全不触发,界面会"闪切",日志里也没有明显报错,是最常见的静默失败。 - transitionName 不唯一:同一个 layout 内两个视图用了相同 name,框架会随机匹配,导致"错误"的元素飞出去。
- ArcMotion 写成了独立过渡:
<arcMotion>必须作为changeBounds(或 slide)的子节点出现,单独放在 transitionSet 里不会生效。 - 监听器忘记移除:共享元素过渡在退出时会反向再执行一次,
onTransitionEnd里写的代码(比如触发 Circular Reveal)会被执行两次。RevealActivity 里特意做了transition.removeListener(this),这是容易被忽略的细节。
更多可练手的过渡组合
项目res/transition/目录下还有几份现成的组合模板,建议配合本篇的 ArcMotion 一起调试:
- slide_and_changebounds.xml:Slide 与 ChangeBounds 并行
- slide_and_changebounds_sequential.xml:两者顺序执行(
transitionOrdering="sequential") - slide_and_changebounds_sequential_with_interpolators.xml:为不同阶段指定不同插值器(bounce、decelerate_cubic),节奏感立刻不同
- explode.xml:Explode 过渡 + bounce 插值器
想要完整可运行的工程,可以克隆仓库体验:git clone https://gitcode.com/gh_mirrors/ma/Material-Animations
总结
| 目标 | 改动量 |
|---|---|
| 让共享元素走出弧线轨迹 | 1 份约 10 行的 XML + 1 行 inflate |
| 控制弧线弯曲程度 | 调maximumAngle一个值 |
| 控制出/落节奏 | 换interpolator一个引用 |
Material-Animations 用这个最小示例证明了 Android Transition 框架的可组合性:过渡本身、路径(ArcMotion)、节奏(Interpolator)三者正交,各自独立可调。掌握"XML 定义过渡 → TransitionInflater 加载 → 挂载到 Window/Scene"这条主线后,你几乎可以用同样套路拼装出任何定制化的页面转场。
【免费下载链接】Material-AnimationsAndroid Transition animations explanation with examples.项目地址: https://gitcode.com/gh_mirrors/ma/Material-Animations
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考