SystemUI 动画技术全景调研
调研范围:packages/SystemUI/ 全目录(含 AOSP 层 + MIUI 定制层)
调研时间:2026-04-28
代码分支:dev-2604-26q2
目录
一、总览
SystemUI 中共使用 15+ 大类 动画技术,三套体系并存:
体系 代表技术 定位 AOSP 原生属性动画 ValueAnimator / ObjectAnimator / AnimatorSet 最基础、最通用,贯穿全模块 小米 Folme 物理动画 miuix.animation.FolmeMIUI 差异化交互核心,仅 MIUI 层使用 Jetpack Compose 动画 animateXAsState / AnimatedVisibility / Animatable新 UI 层主力,配合自研 SceneTransitionLayout
各类型渗透度排名
排名 动画类型 文件数 说明 1 ValueAnimator 177 最基础的数值驱动器 2 Jetpack Compose Animation 177 新 Compose UI 层主力 3 Folme(小米自研) 151 MIUI 交互动效核心 4 ViewPropertyAnimator 136(调用次) 简洁链式 View 动画 5 Canvas/invalidate 自绘 105 高度定制的绘制动画 6 Blur/RenderEffect 102+79 视觉氛围/高斯模糊 7 Transition Framework 87 布局切换场景 8 Scroller/OverScroller 78 弹性滚动引擎 9 ObjectAnimator 78 精确属性控制 10 AnimatorSet 71 多动画编排 11 SpringAnimation (AndroidX) 51 物理弹性动画 12 Window/Activity 转场 42 窗口/页面过渡 13 ViewFlipper/ViewSwitcher 36 子 View 切换 14 MotionLayout 34 约束布局过渡 15 AnimatedVectorDrawable 269(XML) 图标形变 16 Lottie 24 AE 导出复杂动画 17 FlingAnimation 19 惯性滑动 18 Ripple/涟漪 19 生物识别涟漪 19 PhysicsAnimator 7 AOSP 内部物理引擎
二、Folme 动画(小米自研物理动画框架)
2.1 概述
Folme 是小米 miuix SDK 自研的物理动画框架,基于弹簧物理模型,提供状态机驱动的声明式动画 API。在 MIUI 层使用最广泛(151 个文件),但在 AOSP 层零使用。
2.2 核心 API 入口
入口 调用次数 说明 Folme.useAt(view)688 主入口,绑定到 View 返回 IFolme Folme.useValue(object)217 值动画,驱动非 View 的 float 属性 Folme.use(view)74 备选 View 入口 Folme.state()73 静态状态访问 Folme.clean(target)28 清理资源(onDetachedFromWindow 中调用) Folme.to(...)23 静态快捷方法 Folme.afterFrictionValue(...)13 摩擦力物理计算 Folme.cancel(...)11 取消运行中的动画 Folme.visible()8 可见性动画 Folme.setTo(...)6 立即设置(无动画)
2.3 子 API 链
链式调用 使用次数 说明 .state()641 状态机驱动动画(主导模式 ) .touch()12 触摸反馈(按压缩放/着色) .visible()~12 显隐动画 .hover()2 悬浮效果
2.4 缓动曲线分布
缓动类型 引用次数 说明 SPRING_PHY285 物理弹簧(绝对主导 ) FolmeEase.spring(damping, stiffness)108 弹簧快捷方式 DECELERATE23 减速曲线 FolmeEase.sinOut(duration)13 正弦缓出 SIN_OUT7 正弦缓出(旧写法) FolmeEase.cubicOut(duration)4 三次缓出 其他(sinInOut/quartOut/bezier/linear 等) 各 1-2 少量使用
结论:Folme 几乎全部使用弹簧物理缓动 ,SPRING_PHY + FolmeEase.spring 合计占比 >85%。
2.5 常用动画属性
属性 引用次数 说明 ViewProperty.ALPHA376 最常用 ViewProperty.TRANSLATION_Y256 纵向位移 ViewProperty.SCALE_Y193 纵向缩放(通常与 SCALE_X 成对) ViewProperty.SCALE_X188 横向缩放 ViewProperty.TRANSLATION_X154 横向位移 ViewProperty.Y80 绝对 Y 位置 ViewProperty.X32 绝对 X 位置 ViewProperty.ROTATION16 Z 轴旋转 ViewProperty.TRANSITION_ALPHA16 过渡专用 alpha ViewProperty.HEIGHT6 高度 ViewProperty.ROTATION_X5 X 轴旋转(3D 翻转) ViewProperty.Z5 Z 轴高度
2.6 模块分布
模块 文件数 miuiModules/Keyguard 38 miui/Notification 25 miui/Flip 24 miui/Keyguard 15 miui/QuickSetting 9 miui/StatusBar 8 miuiModules/Notification 8 miuiModules/StatusBar 5 miuiModules/miuiutils 4 miuiModules/Base 4 miuiModules/MiuiBiometrics 2 miuiModules/ControlCenter 2 其他(QuickAppPanel/MiuiCharge) 2 AOSP 层(src/) 0
2.7 典型代码模式
模式一:AnimState 常量定义 + AnimConfig 配置
// FolmeAnimState.java (ControlCenter)
AnimState mShowAnim = new AnimState ( "control_center_detail_show" )
. add (ViewProperty.ALPHA, 1f );
AnimState mHideAnim = new AnimState ( "control_center_detail_hide" )
. add (ViewProperty.ALPHA, 0f );
AnimConfig mAnimConfig = new AnimConfig ()
. setEase (EaseManager. getStyle (EaseManager.EaseStyleDef.SPRING, 300L , 0.99f , 0.6666f ));
// 下拉控制中心面板
AnimState mPanelShowAnim = new AnimState ( "control_panel_show" )
. add (ViewProperty.ALPHA, 1f )
. add (ViewProperty.SCALE_X, 1f )
. add (ViewProperty.SCALE_Y, 1f );
AnimState mPanelHideAnim = new AnimState ( "control_panel_hide" )
. add (ViewProperty.ALPHA, 0f )
. add (ViewProperty.SCALE_X, 0.8f )
. add (ViewProperty.SCALE_Y, 0.8f );
模式二:Per-Property 差异化缓动(AnimSpecialConfig)
// FlipRowAnimationUtils.kt — 每个属性使用不同弹簧参数
val scaleXYCon = AnimSpecialConfig ()
. setEase (EaseManager.EaseStyleDef.SPRING_PHY, 0.95f , 0.25f )
. setDelay ( 50 ) as AnimSpecialConfig
val yCon = AnimSpecialConfig ()
. setEase (EaseManager.EaseStyleDef.SPRING_PHY, 0.98f , 0.45f ) as AnimSpecialConfig
val alphaCon = AnimSpecialConfig ()
. setEase (EaseManager.EaseStyleDef.SPRING_PHY, 0.98f , 0.35f ) as AnimSpecialConfig
notificationAnimConfig = AnimConfig ()
. setSpecial (ViewProperty.SCALE_X, scaleXYCon)
. setSpecial (ViewProperty.SCALE_Y, scaleXYCon)
. setSpecial (ViewProperty.TRANSLATION_Y, yCon)
. setSpecial (ViewProperty.ALPHA, alphaCon)
. setDelay ((index * 50 + 80 ). toLong ())
模式三:Folme.useValue — 值动画(非 View)
// NotificationPanelExpansionAnimator.kt
class NotificationPanelExpansionAnimator @Inject constructor () :
FloatFlowProperty ( "notif_expansion" , 0.001f ), LifecycleOwner {
internal val expansion = MutableStateFlow ( 0f )
private val animator = Folme. useValue (expansion)
private val animConfig = AnimConfig ()
. setEase (EaseManager.EaseStyleDef.SPRING_PHY, 0.9f , 0.35f )
. addListeners ( object : TransitionListener () { .. . })
. enableStartImmediately ( true )
internal fun updateExpansion (ratio: Float , animate: Boolean = true ) {
if (animate) animator. to ( this , ratio, animConfig)
else animator. setTo ( this , ratio, animConfig)
}
}
模式四:Touch 触摸反馈
// NumPadKey.kt — 密码键盘按键
protected fun updateDrawableState () {
if (mLastPressedState) {
Folme. use ( this ). resetTo (mPressedFrom). to (mPressedTo, CONFIG_PRESSED)
} else {
Folme. use ( this ). to (mReleased, CONFIG_RELEASE)
}
}
override fun onDetachedFromWindow () {
super . onDetachedFromWindow ()
Folme. clean ( this ) // 必须清理防止泄漏
}
模式五:复杂状态机(通知 AOD 动画)
// MiuiNotificationAnimationExtensions.kt
if ( ! isWakingUp) {
if (shadeChangeToKeyguard) {
Folme. use (view). setTo (notificationKeyguardState)
. to (notificationAodState, notificationAnimToAodConfig)
} else {
Folme. use (view). to (notificationAodState, notificationAnimToAodConfig)
}
} else {
if (view.viewState.mInjector?.animatingToAod == true ) {
Folme. use (view). cancel ( "wakeup_aod" )
Folme. use (view). to (notificationKeyguardState, notificationAnimWakeUpConfig)
} else {
Folme. use (view). setTo (notificationInitState, AnimConfig (). addListeners ( .. .))
}
}
2.8 完整 API 清单
miuix.animation.Folme // 主入口
miuix.animation.FolmeEase // 缓动快捷方法
miuix.animation.FolmeObject // 对象动画
miuix.animation.IFolme // 接口
miuix.animation.IStateStyle // 状态样式接口
miuix.animation.ITouchStyle // 触摸样式接口
miuix.animation.IHoverStyle // 悬浮样式接口
miuix.animation.IAnimTarget // 动画目标接口
miuix.animation.ValueTarget // 值目标
miuix.animation.ViewTarget // View 目标
miuix.animation.base.AnimConfig // 动画配置
miuix.animation.base.AnimSpecialConfig // 属性级特殊配置
miuix.animation.controller.AnimState // 动画状态定义
miuix.animation.controller.IFolmeStateStyle // 状态样式控制器
miuix.animation.listener.TransitionListener // 过渡监听器
miuix.animation.listener.UpdateInfo // 更新信息
miuix.animation.property.FloatProperty // 浮点属性
miuix.animation.property.ValueProperty // 值属性
miuix.animation.property.ViewProperty // View 属性枚举
miuix.animation.utils.EaseManager // 缓动管理器
miuix.animation.utils.EaseManager.EaseStyle // 缓动样式
miuix.animation.utils.EaseManager.EaseStyleDef // 缓动样式定义
miuix.animation.physics.DynamicAnimation // 动态动画
三、ValueAnimator
3.1 概述
指标 数值 使用文件数 177 import/调用行数 470
ValueAnimator 是 SystemUI 中使用面最广的基础动画 API,作为”数值驱动器”驱动各种属性变化。
3.2 主要使用模式
模式一:0→1 进度驱动器(最常见)
// ScrimController.java:1487
ValueAnimator anim = ValueAnimator. ofFloat ( 0f , 1f );
anim. addUpdateListener (animation -> {
float animAmount = ( float ) animation. getAnimatedValue ();
float alpha = MathUtils. lerp (startAlpha, finalScrimAlpha, animAmount);
int tint = ColorUtils. blendARGB (initialScrimTint, finalScrimTint, animAmount);
updateScrimColor (scrim, alpha, tint);
});
anim. setInterpolator (mInterpolator);
anim. setDuration (mAnimationDuration);
这是 SystemUI 中最普遍的惯用法 :用 0→1 的归一化进度值,在 UpdateListener 中手动计算派生值(alpha、tint、position 等)。一个 Animator 驱动多个属性。
模式二:直接数值应用
ValueAnimator. ofInt (child.actualHeight, child.collapsedHeight). apply {
addUpdateListener { animation ->
child.actualHeight = animation.animatedValue as Int
}
}
模式三:颜色过渡
// ColorSchemeTransition.kt:86
open fun buildAnimator (): ValueAnimator {
val animator = ValueAnimator. ofFloat ( 0f , 1f )
animator.duration = 333
animator. addUpdateListener ( this )
return animator
}
3.3 常用时长
时长 (ms) 出现次数 典型场景 250 46 标准过渡 200 44 快速过渡 300 31 中等过渡 100 29 快速/细微动画 150 24 快速淡入淡出 500 23 长/强调动画 1000 17 缓慢/审慎动画 450 12 复杂过渡 167 7 ~10帧@60fps
200-300ms 是最常用的时长区间 ,占比最高。
3.4 常配合的 Interpolator
Interpolator 使用次数 场景 Interpolators.LINEAR87 透明度渐变、匀速变化 PathInterpolator(自定义曲线)66 精调运动曲线 Interpolators.FAST_OUT_SLOW_IN47 Material Design 标准 DecelerateInterpolator37 进入动画 AccelerateInterpolator31 退出动画 Interpolators.ALPHA_OUT28 淡出 Interpolators.ALPHA_IN26 淡入 Interpolators.LINEAR_OUT_SLOW_IN25 减速曲线 Interpolators.EMPHASIZED13 Material 3 强调 Interpolators.DECELERATE_QUINT7 重度减速
3.5 模块分布(Top 10)
目录 文件数 keyguard/domain/interactor 11 statusbar/ 9 com/android/keyguard/ 8 statusbar/notification/row 6 miui/Keyguard/ 5 animation/ 5 statusbar/phone 4 statusbar/notification/stack 4
四、ObjectAnimator
4.1 概述
ObjectAnimator 直接指定目标对象 + 属性名进行动画。
4.2 最常动画的属性
属性 次数 说明 "alpha" / View.ALPHA53 最多 "translationY" / View.TRANSLATION_Y11 上下滑动 "translationX"7 左右滑动 "scaleX" / "scaleY"10 缩放(成对使用) View.ROTATION4 旋转 "textSize"3 字号动画(充电动画) "transitionAlpha"2 过渡专用 alpha "elevation"1 阴影深度 View.TRANSLATION_Z1 Z 轴平移
4.3 自定义 Property(~25+ 个)
SystemUI 定义了大量自定义 FloatProperty / IntProperty,使用 View tags 存储动画状态:
自定义 Property 文件 用途 ICON_APPEAR_AMOUNTStatusBarIconView.java图标出现状态 DOT_APPEAR_AMOUNTStatusBarIconView.java通知小圆点 TRANSLATE_CONTENTExpandableNotificationRow.java滑动位移 notificationVisibilityNotificationWakeUpCoordinator.kt唤醒可见性 ABSOLUTE_X / ABSOLUTE_YAnimatableProperty.java布局安全的绝对定位 WIDTH / HEIGHTAnimatableProperty.java尺寸动画 KEY_DRAWABLE_ROTATEKeyButtonDrawable.java导航键旋转 mDozeAmountStatusBarStateControllerImpl.javaDoze 过渡 topRoundness / bottomRoundnessRoundable.kt通知圆角 fold_header_alpha / fold_header_trans_yFoldNotificationHeaderController.ktMIUI 折叠头部
4.4 典型代码
// StatusBarIconView.java:126 — 自定义 FloatProperty
private static final Property < StatusBarIconView, Float > ICON_APPEAR_AMOUNT
= new FloatProperty< StatusBarIconView >( "iconAppearAmount" ) {
@ Override public void setValue (StatusBarIconView object , float value ) {
object. setIconAppearAmount (value);
}
@ Override public Float get (StatusBarIconView object ) {
return object. getIconAppearAmount ();
}
};
// 使用:
mIconAppearAnimator = ObjectAnimator. ofFloat ( this , ICON_APPEAR_AMOUNT, 1.0f );
// WindowMagnificationController.java:1663 — PropertyValuesHolder 多属性
ObjectAnimator scaleAnimator = ObjectAnimator. ofPropertyValuesHolder (mMirrorView,
PropertyValuesHolder. ofFloat (View.SCALE_X, 1 , mBounceEffectAnimationScale, 1 ),
PropertyValuesHolder. ofFloat (View.SCALE_Y, 1 , mBounceEffectAnimationScale, 1 ));
scaleAnimator. setDuration (mBounceEffectDuration);
scaleAnimator. start ();
五、AnimatorSet(动画编排)
5.1 概述
5.2 playTogether vs playSequentially
方式 次数 占比 playTogether()79 88.8% playSequentially()10 11.2%
比例约 8:1 ,并行动画是常态,顺序动画仅用于明确的”先A后B”场景。
5.3 playSequentially 使用场景
全部 10 处均为”状态A → 状态B”的视觉序列:
FaceScanningOverlay.kt — cameraProtect 后 rimAppear
ControlViewHolder.kt — fadeOut 后 fadeIn
KeyguardIndicationTextView.java — fadeOut 后 fadeIn
AuthRippleView.kt — dwellPulseOut 后 expandDwell
PasswordTextView.java/kt — overshoot 后 settle
KeyguardPinBasedInputView.java/kt — scaleDown 后 scaleUp
LockPatternView.java — activation 后 deactivation
5.4 典型代码
// ToastDefaultAnimation.kt:41 — 入场动画编排
val sX = ObjectAnimator. ofFloat (view, "scaleX" , 0.9f , 1f ). apply {
interpolator = scaleInterp; duration = 333
}
val sY = ObjectAnimator. ofFloat (view, "scaleY" , 0.9f , 1f ). apply {
interpolator = scaleInterp; duration = 333
}
val vA = ObjectAnimator. ofFloat (view, "alpha" , 0f , 1f ). apply {
interpolator = linearInterp; duration = 66
}
val tA = ObjectAnimator. ofFloat (text, "alpha" , 0f , 1f ). apply {
interpolator = linearInterp; duration = 283 ; startDelay = 50
}
return AnimatorSet (). apply { playTogether (sX, sY, vA, tA, iA) }
六、ViewPropertyAnimator(view.animate())
6.1 概述
最简洁的 View 动画 API,链式调用。
6.2 常用链式属性
属性 次数 .alpha()13 .setDuration()5 .scaleX() / .scaleY()各 2 .translationX()1
6.3 模块分布(Top 10)
目录 调用数 statusbar/ 19 statusbar/notification/row 15 shade/ 7 miui/QuickSetting/customize 7 miui/QuickSetting/qs 6 miuiModules/Notification/utils 6 selectiontoolbar/ 5 miui/StatusBar/pipeline 5 miui/Flip/tinyPanel 5
6.4 典型代码
// StackScrollerDecorView.java
view. animate (). cancel ();
view. animate ()
. alpha (endValue)
. setInterpolator (interpolator)
. setDuration (mAnimationDuration)
. setListener ( new AnimatorListenerAdapter () { ... });
七、SpringAnimation / DynamicAnimation(AndroidX 物理动画)
7.1 概述
7.2 弹簧参数配置一览
位置 Stiffness Damping Ratio 场景 SwipeHelper550f 0.52f 滑动回弹 MediaCarouselScrollHandlerSTIFFNESS_LOW DAMPING_RATIO_LOW_BOUNCY 滚动停靠(弹跳) NotificationShadeDepthControllerSTIFFNESS_LOW DAMPING_RATIO_NO_BOUNCY 模糊深度 NotificationShadeDepthController(唤醒)STIFFNESS_HIGH DAMPING_RATIO_NO_BOUNCY 快速清除模糊 PhysicsPropertyAnimator380f 1.3f(过阻尼) 通知栈动画 MagneticNotificationRowManager(脱离)800f 0.95f 磁性脱离 MagneticNotificationRowManager(回弹)550f 0.6f 回弹 MagneticNotificationRowManager(吸附)850f 0.95f 磁性吸附
7.3 常用动画属性
属性 引用次数 ALPHA 38 TRANSLATION_X 15 TRANSLATION_Y 13 SCALE_X 4 SCALE_Y 4 ROTATION 1
7.4 模块分布(Top 10)
目录 引用数 accessibility/floatingmenu 43 animation/lib 23 statusbar/notification/stack 19 navigationbar/gestural 14 animation/src 14 miui/Keyguard/screenfade 13 miuiModules/StatusBar/animation 12 unfold/progress 11 volume/dialog 10 miuiModules/Notification/media 10
7.5 典型代码
// MagneticNotificationRowManagerImpl.kt:77
private val detachForce = SpringForce ()
. setStiffness (DETACH_STIFFNESS) // 800f
. setDampingRatio (DETACH_DAMPING_RATIO) // 0.95f
private val snapForce = SpringForce ()
. setStiffness (SNAP_BACK_STIFFNESS) // 550f
. setDampingRatio (SNAP_BACK_DAMPING_RATIO) // 0.6f
// NotificationShadeDepthController.kt:494
shadeAnimation. setStiffness (SpringForce.STIFFNESS_LOW)
shadeAnimation. setDampingRatio (SpringForce.DAMPING_RATIO_NO_BOUNCY)
八、FlingAnimation(惯性动画)
8.1 概述
8.2 使用场景
文件 场景 ExpandHelper.java通知展开/折叠 SwipeHelper.java滑动删除 KeyguardAffordanceView.java锁屏快捷入口 BouncerSwipeTouchHandler.kt密码界面滑动 ShadeAnimationInteractor*.kt(4 文件)通知栏 fling MenuAnimationController.java辅助功能浮动菜单 TinyKeyguardPanelViewControllerImpl.kt翻盖锁屏 FlingOnBackAnimationCallback.kt预测性返回手势
8.3 摩擦力参数
FLING_FRICTION = 6f — 返回手势(FlingOnBackAnimationCallback)
动态传入 friction — 浮动菜单(MenuAnimationController)
8.4 典型代码
// FlingOnBackAnimationCallback.kt:121
FlingAnimation ( FloatValueHolder ())
. setStartValue ((lastBackEvent?.progress ?: 0f ) * SCALE_FACTOR)
. setFriction (FLING_FRICTION)
. setStartVelocity (velocityTracker.xVelocity)
. setMinValue ( 0f )
. setMaxValue (SCALE_FACTOR)
九、PhysicsAnimator(AOSP SystemUI 自研)
9.1 概述
AOSP SystemUI 内部封装,支持在一个 API 中混合弹簧和 fling。
9.2 使用位置
文件 场景 SwipeHelper.java通知滑动回弹 MediaCarouselScrollHandler.kt媒体轮播滚动/fling ExpandableNotificationRow.java取消物理动画 DragToInteractView.kt气泡拖拽交互 MiuiQSContainer.ktMIUI 快设容器
9.3 典型代码
// MediaCarouselScrollHandler.kt:333
PhysicsAnimator. getInstance ( this )
. spring (
CONTENT_TRANSLATION,
newTranslation,
startVelocity = 0.0f ,
config = translationConfig,
)
. start ()
十、Jetpack Compose Animation
10.1 概述
指标 数值 使用文件数 177 导入 compose.animation 的文件 160
Compose 声明式动画是新 UI 层的主力,覆盖锁屏、通知、快设、音量面板等核心场景。
10.2 API 使用分布
状态驱动动画(animateXAsState)
API 使用次数 代表文件 animateFloatAsState45 ActionList.kt, CommunalHub.kt, ShadeScene.kt, PinBouncer.kt animateColorAsState16 PinBouncer.kt, PlatformSlider.kt animateDpAsState15 ColumnVolumeSliders.kt, PinBouncer.kt animateIntAsState1 NavBarPill.kt
高级 Composable 动画
API 使用次数 代表文件 AnimatedVisibility69 CommunalHub.kt(7), Media.kt(6), ColumnVolumeSliders.kt(3) AnimatedContent24 QuickSettingsShadeOverlay.kt, FooterActions.kt, Toolbar.kt Crossfade7 Media.kt(专辑封面切换), AlternateBouncer.kt updateTransition~8 ResizeableItemFrame.kt, Selection.kt, EditTile.kt rememberInfiniteTransition1 CommunalContainer.kt(背景渐变) MutableTransitionState~12 AlternateBouncer.kt, NavBarPill.kt
底层/手动控制动画
API 使用次数 代表文件 Animatable(创建)51 PatternBouncer.kt(5), PinBouncer.kt, ShadeHeader.kt, NavBarPill.kt animateTo / snapTo 调用~299 广泛分布 animateContentSize13 VolumeSlider.kt, Media.kt(4), EditTile.kt LaunchedEffect(总计)~243 动画相关子集驱动 Animatable 协程
AnimationSpec 类型
Spec 使用次数 常见参数 tween()187 150-500ms, CubicBezierEasing, Easings.StandardAccelerate spring()~69 StiffnessMediumLow, StiffnessHigh, DampingRatioNoBouncy snap()13 零时长立即切换 keyframes4 NavBarPill.kt, BounceableTileViewModel.kt
tween 占绝对主导(187 vs 69 spring) ,Compose 层更偏好基于时长的动画而非物理弹簧。
10.3 SceneTransitionLayout(自研场景过渡框架)
SystemUI 构建了自研的 SceneTransitionLayout 系统(compose/scene/),拥有 40 个场景过渡定义文件 (compose/features/.../transitions/)。使用 TransitionBuilder DSL:
// FromLockscreenToGoneTransition.kt
fun TransitionBuilder . lockscreenToGoneTransition () {
spec = tween (durationMillis = 500 )
fractionRange (end = 0.3f , easing = Easings.PredictiveBack) {
fade (LockscreenElementKeys.Region.Upper)
fade (LockscreenElementKeys.LockIcon)
translate (LockscreenElementKeys.Region.Upper, y = ( - 48 ).dp)
translate (LockscreenElementKeys.Notifications.Stack, y = ( - 72 ).dp)
}
}
这是锁屏↔通知栏↔快设等场景间过渡的主要动画机制 ,不使用标准的 AnimatedContent。
10.4 模块分布
功能区域 文件数 Scene transitions(框架+定义) 63 Keyguard/Lockscreen/Bouncer 16 Screen Capture/Recording 13 Quick Settings 11 Volume Panel 9 Communal Hub 8 Ambient Cue 5 Notifications 4 Shade 3 Media Player 3
10.5 典型代码
Animatable + LaunchedEffect 弹跳动画
// ShadeHeader.kt:866 — 循环弹跳
val animatable = remember { Animatable ( 0f ) }
LaunchedEffect (isEnabled) {
if (isEnabled) {
while ( true ) {
animatable. animateTo (
targetValue = with (density) { - ( 10 .dp). toPx () },
animationSpec = tween ( 200 , easing = CubicBezierEasing ( 0.15f , 0f , 0.23f , 1f )))
animatable. animateTo ( 0f ,
tween ( 167 , easing = CubicBezierEasing ( 0.74f , 0f , 0.22f , 1f )))
animatable. animateTo (
with (density) { - ( 5 .dp). toPx () },
tween ( 150 , easing = CubicBezierEasing ( 0.62f , 0f , 0.35f , 1f )))
animatable. animateTo ( 0f ,
tween ( 117 , easing = CubicBezierEasing ( 0.67f , 0f , 0.51f , 1f )))
delay ( 1000 )
}
}
}
PatternBouncer — 多 Animatable 映射
// PatternBouncer.kt:117
val dotScalingAnimatables = remember (dots) { dots. associateWith { Animatable ( 1f ) } }
val lineFadeOutAnimatables = remember (dots) { dots. associateWith { Animatable ( 1f ) } }
LaunchedEffect (currentDot, isAnimationEnabled) {
dotScalingAnimatables.entries. forEach { (dot, animatable) ->
scope. launch {
if (dot == currentDot) {
animatable. animateTo (SELECTED_DOT_DIAMETER_DP / DOT_DIAMETER_DP. toFloat (),
tween (easing = Easings.StandardAccelerate))
} else {
animatable. animateTo ( 1f , tween (easing = Easings.StandardDecelerate))
}
}
}
}
Crossfade 媒体封面切换
// Media.kt:946
Crossfade (targetState = image, modifier = modifier) { imageOrNull ->
val backgroundImage = imageOrNull?. let { (it as Icon.Loaded). asImageBitmap () }
if (backgroundImage != null ) {
Image (bitmap = backgroundImage, contentScale = ContentScale.Crop,
modifier = Modifier. fillMaxSize (). drawWithContent {
drawContent ()
drawRect (brush = Brush. radialGradient ( .. .))
})
}
}
rememberInfiniteTransition — 无限循环渐变
// CommunalContainer.kt:447
val infiniteTransition = rememberInfiniteTransition ()
val centerFraction by infiniteTransition. animateFloat (
initialValue = 0f , targetValue = 1f ,
animationSpec = infiniteRepeatable (
animation = tween (ANIMATION_DURATION_MS,
easing = CubicBezierEasing ( 0.33f , 0f , 0.67f , 1f )),
repeatMode = RepeatMode.Reverse,
))
十一、Transition Framework(场景切换)
11.1 概述
指标 数值 使用文件数 87 TransitionManager.beginDelayedTransition 调用13
11.2 Transition 类型使用
类型 实例化次数 文件 TransitionSet6 NotificationInfo, BaseBlueprintTransition, ClockSizeTransition Fade(OUT + IN)4 NotificationInfo, NotificationConversationInfo ChangeBounds3 NotificationInfo, BaseBlueprintTransition AutoTransition3 ChannelEditorListView, BiometricViewSizeBinder, KeyguardClockViewBinder Explode0 未使用 Slide0 未使用
11.3 LayoutTransition
文件 场景 BatteryMeterView.java电池图标显隐 NavigationBarView.java导航栏按钮变化
11.4 常见模式
// NotificationInfo.java — TransitionSet 组合
TransitionSet transitionSet = new TransitionSet ();
transitionSet. setOrdering (TransitionSet.ORDERING_TOGETHER);
transitionSet. addTransition ( new Fade (Fade.OUT))
. addTransition ( new ChangeBounds ())
. addTransition ( new Fade (Fade.IN));
TransitionManager. beginDelayedTransition ( this , transitionSet);
十二、MotionLayout
12.1 概述
12.2 功能分布
功能 文件 锁屏 PIN/图案/密码输入布局 keyguard_pin_motion_layout.xml, keyguard_pattern_motion_layout.xml, keyguard_password_motion_layout.xml + 对应 MotionSceneQS 头部折叠/展开 combined_qs_header.xml, combined_qs_header_scene.xml音量面板铃声模式抽屉 volume_dialog_top_section.xml, volume_dialog_ringer_drawer_motion_scene.xml
12.3 关键文件
Java/Kotlin : ShadeHeaderController.kt, QsBatteryModeController.kt, VolumeDialogRingerViewBinder.kt, KeyguardPasswordView.kt, KeyguardPatternView.kt, KeyguardPINView.kt, NoRemeasureMotionLayout.kt
十三、Lottie
13.1 概述
13.2 功能分布
功能区域 文件数 JSON 资源数 说明 生物识别(指纹/面部) 7 ~30 指纹→错误、错误→成功、认证中等状态切换 触摸板手势教程 4 8 返回/Home/最近/切换 教学动画 功能键教程 4 2 Action Key 教学+成功 锁屏设备入口 1 2 UDFPS AOD/锁屏指纹 音量面板 2 3 audio_bars_in/playing/out 截屏 1 — 截屏架动画 后置显示 1 2 折叠/翻转提示 MIUI 通知 2 — 抬头通知、设备通知
13.3 JSON 资源分类
分类 文件数 代表文件 SFPS 侧面指纹 ~30 sfps_fp_to_error_*.json(0/90/180/270度旋转变体)面部对话框 6 face_dialog_authenticating.json, face_dialog_dark_to_checkmark.json指纹对话框 7 fingerprint_dialog_fp_to_error.json触摸板教程 8 back_gesture_edu.json, home_gesture_success.json音量音频条 3 audio_bars_in.json, audio_bars_playing.jsonUDFPS 2 udfps_aod_fp.json, udfps_lockscreen_fp.json
十四、传统 View Animation(Tween/Frame)
14.1 概述
指标 数值 代码引用行数 331 XML anim 资源文件 71
14.2 XML 动画类型分布
类型 文件数 <set>(组合)35 <translate>6 <objectAnimator>5 <alpha>4
14.3 常用时长
时长 (ms) 出现次数 说明 83 62 ~5帧@60fps,锁屏图标状态切换 100 42 快速切换 133 36 ~8帧 183 28 略慢 117 28 ~7帧 250 22 标准过渡 167 18 ~10帧
14.4 MIUI 特有 XML 动画
模块 文件 场景 miui/Notification dialog_bottom_in.xml, dialog_bottom_out.xml底部弹窗进出 miui/StatusBar spring_phy.xml, translate_enter/exit.xml弹簧动画/平移进出 miui/Keyguard shrink_to_bottom.xml, stretch_from_bottom.xml收缩/展开动画 miui/Keyguard keyguard_face_unlock_error_*_rotate.xml面部解锁错误旋转
十五、AnimatedVectorDrawable(矢量动画)
15.1 概述
指标 数值 AVD XML 文件数 257 代码引用文件数 30
15.2 动画图标分类
分类 代表文件 说明 QS 磁贴图标 qs_bluetooth_icon_off/on, qs_hotspot_icon_off开关状态切换动画 锁图标状态 lock_lock.xml, lock_unlock.xml, lock_to_error.xml锁→解锁→错误 设备控制图标 ic_device_outlet_off_anim.xml, ic_device_lock_on_anim.xmlIoT 设备状态 PIN 密码点 pin_dot_avd.xml, bouncer_shape_*.xml密码输入动画 媒体播放 ic_media_pause_button.xml暂停按钮 旋转按钮 ic_sysbar_rotate_button_ccw_start_*.xml屏幕旋转 进度指示器 progress_indeterminate_horizontal_material_trimmed.xml不确定进度条 勿扰模式 avd_dnd_to_on.xmlDnD 开关
十六、模糊/RenderEffect 动画
16.1 概述
技术 文件数 说明 MiBlurCompat(MIUI 私有) 57 MIUI 专属高性能模糊 标准 RenderEffect 22 Android 12+ 标准 API BlurUtils 102 (含引用)SystemUI 模糊工具类
比例约 2.6:1 ,MiBlurCompat 占主导。
16.2 MiBlurCompat API
setMiBackgroundBlurRadiusCompat (radius)
setMiViewBlurModeCompat (mode) // DRAW_RECT_AND_BLEND, CLEAR_BLUR, SAVE_LAYER...
addMiBackgroundBlendColorCompat ( 0x4D000000 , SRC_OVER)
setPassWindowBlurEnabledCompat (boolean)
setMiBackgroundBlurEnhance (view, enabled, callback)
16.3 标准 RenderEffect 使用位置
文件 场景 AnimatedActionBackgroundDrawable.kt通知操作按钮模糊 NotificationStackScrollLayout*.java通知栈模糊 NotificationPanelViewController.java面板模糊 ScrimView.java遮罩模糊 TinyKeyguardPanelViewControllerImpl.kt翻盖锁屏壁纸模糊 KeyguardMaskFadeEffectController.kt时钟 RuntimeShader 效果
16.4 模糊半径值
常用范围:0(关闭)、30、40、100。NotificationShadeDepthController 通过 blurRadiusOfRatio(ratio) 将通知栏展开比例映射到模糊半径。
16.5 典型代码
// MiuiKeyguardBlurInteractor.kt
if (radius > 0 ) {
setPassWindowBlurEnabledCompat ( true )
setMiBackgroundBlurModeCompat (SAVE_LAYER)
setMiBackgroundBlurRadiusCompat (radius)
setMiViewBlurModeCompat (DRAW_RECT_AND_BLEND)
clearMiBackgroundBlendColorCompat ()
addMiBackgroundBlendColorCompat ( 0x4D000000 , SRC_OVER)
} else {
setPassWindowBlurEnabledCompat ( false )
setMiBackgroundBlurModeCompat (CLEAR_BLUR)
}
// NotificationShadeDepthController.kt — 动态计算模糊
combinedBlur = max (combinedBlur, blurUtils. blurRadiusOfRatio (qsExpandedRatio))
combinedBlur = max (combinedBlur, blurUtils. blurRadiusOfRatio (transitionToFullShadeProgress))
var shadeRadius = max (combinedBlur, wakeAndUnlockBlurRadius)
shadeRadius *= ( 1 - brightnessMirrorSpring.ratio)
十七、Canvas/invalidate 自绘动画
17.1 概述
通过 onDraw(Canvas) + invalidate() / postInvalidateOnAnimation() 驱动的逐帧自绘动画。
17.2 代表性自绘动画 View
View 场景 LightRevealScrim.kt锁屏唤醒光线揭示动画(Shader) AuthRippleView.kt生物识别认证涟漪效果 BackPanel.kt预测性返回手势箭头绘制 ReceiverChipRippleView.kt媒体 tap-to-transfer 涟漪 FaceScanningOverlay.kt面部扫描叠加层 ScreenDecorHwcLayer.kt屏幕挖孔/圆角装饰 NotificationBackgroundView.java通知行背景(圆角) ActivatableNotificationView.java通知触摸激活背景 KeyguardAffordanceView.java锁屏快捷入口圆圈 NavigationHandle.java手势导航药丸
18.1 概述
18.2 自定义滚动行为
实现 文件 场景 OverScrollerWrapper / OverScrollerInterface通知栈 封装标准 OverScroller SingleShadeLockScreenOverScroller锁屏 锁屏通知栏过度滚动 ShadeOverScroller下拉面板 面板过度滚动 MIUI 自定义 OverScroller miui/systemui/notification/widget/内含 FolmeScroller + ViscousFluidInterpolator
18.3 使用此类的 View
NotificationStackScrollLayout, MiuiQSFragment, MiuiPagedTileLayout, KeyguardPanelViewController, FlipRowContainerController, TinyViewPagerDelegate, WalletCardCarousel
十九、Window/Activity 转场动画
19.1 概述
19.2 使用方式
API 次数 场景 makeSceneTransitionAnimation5 Controls 管理页面(ControlsProviderSelectorActivity 等) makeCustomAnimation6 DetailDialog, AssistManager, EmergencyButton(多数为 0,0 即无动画) makeSceneTransitionAnimation(共享元素)1 LongScreenshotActivity overridePendingTransition2 BrightnessDialog(fade_in/out), AppClipsActivity(0,0)
二十、Interpolator(缓动曲线)汇总
20.1 总览
SystemUI 中使用了 30+ 种 Interpolator,来自 4 大来源。
20.2 AOSP 标准 Interpolator
Interpolator 典型场景 LinearInterpolator匀速变化 AccelerateDecelerateInterpolator标准加减速 AccelerateInterpolator退出动画 DecelerateInterpolator进入动画 OvershootInterpolator超越目标值后回弹 AnticipateOvershootInterpolator先后退再超越 PathInterpolator(23 文件)自定义贝塞尔曲线
20.3 AOSP SystemUI Interpolators 工具类
常量 场景 Interpolators.LINEAR线性(87次) Interpolators.FAST_OUT_SLOW_INMaterial 标准(47次) Interpolators.ALPHA_IN / ALPHA_OUT淡入/淡出 Interpolators.EMPHASIZEDMaterial 3 强调 Interpolators.EMPHASIZED_DECELERATEM3 强调减速 Interpolators.STANDARD / STANDARD_DECELERATE标准/标准减速 Interpolators.TOUCH_RESPONSE触摸响应 Interpolators.DECELERATE_QUINT五次减速
20.4 MIUI 自定义 Interpolator
PhysicBasedInterpolator
基于阻尼谐振子数学模型:e^(r*t) * (c1*cos(w*t) + c2*sin(w*t)) + 1.0
// RowAnimationUtils.kt — 通知触摸缩放
// 按下: damping=0.9, response=0.8, duration=450ms (缩放到 0.95)
// 抬起: damping=0.6, response=0.556, duration=450ms (回到 1.0)
使用位置:RowAnimationUtils.kt, FlipRowAnimationUtils.kt, KeyguardMoveHelper.java, EdgePanelParams.kt, QSAnimation.kt, ModalControllerImpl.kt, MiuiNotificationAnimationExtensions.kt
SpringInterpolator
同样基于阻尼谐振子,但继承 BaseInterpolator 支持 XML 属性。
// MiuiAnimationUtils.kt
generalWakeupTranslateAnimation: damping = 0.95 , response = 0.8571 , duration = 700ms
generalWakeupAlphaAnimation: damping = 0.9 , response = 0.86 , duration = 350ms
generalWakeupScaleAnimation: damping = 0.9 , response = 0.86 , duration = 350ms
MiuiInterpolators 工具类
MIUI_ALPHA_IN = new SineEaseOutInterpolator ();
MIUI_ALPHA_OUT = new SineEaseOutInterpolator ();
CUBIC_EASE_OUT = new CubicEaseOutInterpolator ();
CUBIC_EASE_IN_OUT = new CubicEaseInOutInterpolator ();
EXP_EASE_OUT = new ExponentialEaseOutInterpolator ();
ViscousFluidInterpolator
从 miuix.overscroller 移植,用于通知栈 fling 减速,VISCOUS_FLUID_SCALE = 8.0f。
20.5 Miuix SDK Interpolator
Interpolator 包路径 CubicEaseInInterpolatormiuix.view.animationCubicEaseOutInterpolatormiuix.view.animationCubicEaseInOutInterpolatormiuix.view.animationExponentialEaseOutInterpolatormiuix.view.animationSineEaseOutInterpolatormiuix.view.animation
20.6 Compose Easing
Easing 使用场景 CubicBezierEasing(...)自定义贝塞尔曲线 Easings.StandardAccelerate标准加速 Easings.StandardDecelerate标准减速 Easings.PredictiveBack预测性返回 Easings.Linear线性 FastOutSlowInEasingMaterial 标准
20.7 其他自定义 Interpolator
Interpolator 文件 用途 BounceInterpolatorstatusbar/phone/BounceInterpolator.java弹跳效果 SystemUIInterpolatorsvolume/SystemUIInterpolators.java音量面板 QSExpansionPathInterpolatorQS 快设展开曲线 FontInterpolator / TextInterpolatoranimation 文字形变 TruncatedInterpolatorlowlight 截断插值
二十一、架构总结与演进趋势
21.1 三套动画体系并存
┌─────────────────────────────────────────────────────────┐
│ SystemUI 动画架构 │
├──────────────────┬──────────────────┬───────────────────┤
│ AOSP 原生层 │ MIUI 定制层 │ Compose 新 UI 层 │
├──────────────────┼──────────────────┼───────────────────┤
│ ValueAnimator │ Folme │ animateXAsState │
│ ObjectAnimator │ FolmeEase │ AnimatedVisibility │
│ AnimatorSet │ AnimState │ Animatable │
│ SpringAnimation │ AnimConfig │ SceneTransition │
│ FlingAnimation │ MiBlurCompat │ AnimatedContent │
│ PhysicsAnimator │ PhysicBasedInterp│ Crossfade │
│ Transition │ MiuiInterpolators│ updateTransition │
│ MotionLayout │ │ │
├──────────────────┼──────────────────┼───────────────────┤
│ src/ │ miui*/ │ compose/ │
│ 通用基础动画 │ MIUI 差异化交互 │ 新场景过渡+声明式UI │
└──────────────────┴──────────────────┴───────────────────┘
21.2 关键洞察
Folme 是 MIUI 层的绝对核心 (151 文件),但在 AOSP 层零使用,形成了清晰的分层边界。
ValueAnimator.ofFloat(0f, 1f) 作为万能进度驱动器 是整个代码库中最普遍的惯用法,一个 Animator 驱动多个派生属性值。
弹簧物理是 MIUI 的动画哲学 :Folme 的 SPRING_PHY 占比 >85%,几乎所有 MIUI 交互都使用弹簧缓动。
Compose 层偏好 tween 而非 spring (187 vs 69),与 MIUI 层的弹簧偏好形成对比。
自研 SceneTransitionLayout 是最大的动画投资 (40 个过渡定义文件),是锁屏↔通知栏↔快设等核心场景的过渡基础。
模糊动画是 SystemUI 的视觉基石 (180+ 文件),MiBlurCompat 占主导(2.6:1)。
AVD 是最多的动画资源文件 (257 个 XML),主要用于 QS 磁贴和锁屏图标的状态切换。
21.3 演进趋势
方向 证据 新 UI → Compose Animation 177 文件已迁移,Scene Framework 是新架构核心 MIUI 交互 → Folme 几乎所有 MIUI 新代码使用 Folme 状态机模式 传统 View Animation 减少 XML anim 文件集中在旧模块,新代码少用 MotionLayout 稳定但不扩展 仅用于 PIN/Pattern/QS Header/Volume,未见新增 Lottie 定位于复杂状态动画 集中在生物识别和教程,不会替代代码动画
本文档基于 dev-2604-26q2 分支代码静态分析生成,统计数据为近似值。