Skip to main content

Modifier Architecture

1. 文档定位

本文档定义 Modifier、组件 NodeSpecTheme/Defaults 的当前边界。

目标是保证新增能力时落点明确,避免语义混放。

2. 当前基线(2026-07)

  1. identity 入口统一为 ModifierModifier.Empty 已移除)
  2. 文本语义类历史 modifier(如 textColor/textSize)已退场
  3. weight/align/FlexibleSpacer 仅通过 RowScope/ColumnScope/BoxScope 暴露
  4. 系统栏/键盘 inset 适配走组件侧 Modifier.systemBarsInsetsPadding(...)Modifier.imeInsetsPadding(...)(若 Activity 使用 adjustResize,通常不再叠加 imeInsetsPadding,避免双重位移)
  5. 列表容器策略已收口为容器参数:reusePolicysharePool)与 motionPolicydisableItemAnimator/animateInsert/animateRemove/animateMove/animateChange
  6. 键盘焦点跟随已收口为垂直容器参数:focusFollowKeyboard;当前覆盖 LazyColumnLazyVerticalGridVerticalPagerScrollableColumn
  7. LazyRowHorizontalPagerScrollableRow 不暴露 focusFollowKeyboard,避免“可调用但无效”的 API 漂移
  8. 背景资源支持 Modifier.backgroundDrawableRes(resId);与 backgroundColor 同时存在时,drawable 优先;当同时存在 cornerRadius 时自动裁剪内容,clip() 仍可作为通用强制裁剪开关
  9. 内容尺寸动画支持 Modifier.animateContentSize(...);renderer 会在 patch 前自动插入 AnimatedSizeHost,以“真实测量尺寸插值”参与父布局重排(非 graphicsLayer 视觉缩放),并保留 AnimationSpec 的 easing/spring/keyframes/repeat 语义(含 reverse 终态)
  10. 约束 parent-data 支持 Modifier.layoutId(...)Modifier.constrainAs(...)Modifier.constrain(...);仅对 ConstraintLayout 子节点生效
  11. 图形绘制 modifier 已接入:Modifier.drawBehindModifier.drawWithContentModifier.drawWithCache(以及短写 draw/drawCache);执行顺序按 modifier 链稳定,drawWithContent 可显式控制内容透传;底层执行保证 DrawRoundRect 四角半径与 Drawable + DrawPaint 组合语义不丢失
  12. 声明式焦点与硬件键盘输入已接入:focusable/focusRequester/focusProperties/focusGroup/onFocusChanged/onPreviewKeyEvent/onKeyEvent 映射原生 View 焦点搜索,并由 LocalFocusManager 提供会话级移动与清除能力
  13. 统一嵌套滚动协议已接入:Modifier.nestedScroll(connection, dispatcher) 通过透明宿主映射 AndroidX nested-scrolling parent/child 链,覆盖 pre/post scroll、pre/post fling、Lazy/Pager/普通滚动容器与自定义 drag/transform pan
  14. 高级阴影已接入:dropShadow/dropShadows 绘制在节点内容之前,innerShadow/innerShadows 绘制在完整内容之后;均支持有序多层、独立 shape、blur/spread/offset/color,并与 elevation/zIndex 解耦

3. API 清单(全量扫描)

3.1 扫描基线(src/main

本节 API 清单来自仓库实时扫描,命令口径固定为:

rg "^\s*(public\s+)?(internal\s+)?fun\s+(<[^>]+>\s*)?Modifier\.([A-Za-z0-9_]+)\(" --glob "**/src/main/**/*.kt"
rg "^\s*(public\s+)?(internal\s+)?fun\s+(RowScope|ColumnScope|BoxScope|ConstraintLayoutScope)\."

当前扫描结果(2026-07):

  1. fun Modifier.* 声明总数(含重载、含 scoped 内部定义):76
  2. fun Modifier.* 唯一 API 名称数:62
  3. scoped modifier 声明总数:5RowScope/ColumnScope/BoxScope
  4. renderer internal modifier 扩展:1(仅内部解析能力)

3.2 分组说明(按架构边界)

  1. ui-contract 通用修饰:平台无关的基础 Modifier 契约入口。
  2. gesture 动作输入:手势 DSL,依赖手势状态对象与策略内核。
  3. graphics 绘制:绘制阶段 API(含 draw* 短写)。
  4. graphics 阴影装饰:平台无关阴影规格,由 Android decoration layer 执行。
  5. animation 尺寸动画animateContentSize 布局尺寸过渡入口。
  6. host-android interop:Android 平台互操作能力(nativeView/android*)。
  7. renderer internal 解析/策略:仅 renderer 内部使用,不给业务侧依赖。

3.3 Global Modifier APIs(含 internal)

API模块/命名空间可见性用途备注生效范围补充说明
paddingviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置内容内边距全局3 个重载(all/horizontal+vertical/四边)
marginviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置外边距(layout params 侧)全局3 个重载
sizeviewcompose-ui-contract / com.viewcompose.ui.modifierpublic同时设置宽高全局固定像素语义(框架单位)
widthviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置宽度全局与父容器布局规则共同生效
heightviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置高度全局与父容器布局规则共同生效
minWidthviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置最小宽度约束全局作用于 View.minimumWidth
minHeightviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置最小高度约束全局作用于 View.minimumHeight
fillMaxWidthviewcompose-ui-contract / com.viewcompose.ui.modifierpublic宽度填充父容器全局语义等价 width(MATCH_PARENT)
fillMaxHeightviewcompose-ui-contract / com.viewcompose.ui.modifierpublic高度填充父容器全局语义等价 height(MATCH_PARENT)
fillMaxSizeviewcompose-ui-contract / com.viewcompose.ui.modifierpublic宽高同时填充父容器全局语义等价 size(MATCH_PARENT, MATCH_PARENT)
offsetviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置平移偏移全局映射 translationX/translationY
layoutIdviewcompose-ui-contract / com.viewcompose.ui.modifierpublic标记子项布局 ID指定容器主要用于 ConstraintLayout 子项匹配
systemBarsInsetsPaddingviewcompose-ui-contract / com.viewcompose.ui.modifierpublic应用系统栏 inset 内边距全局(容器感知)可按四边开关
imeInsetsPaddingviewcompose-ui-contract / com.viewcompose.ui.modifierpublic应用软键盘 inset 内边距全局(容器感知)默认仅 bottom=true
backgroundColorviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置背景色全局backgroundDrawableRes 同时存在时优先级较低
backgroundDrawableResviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置 drawable 资源背景全局cornerRadius 组合时自动裁剪
borderviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置边框宽度与颜色全局依赖 surface style 管线渲染
cornerRadiusviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置圆角半径全局3 个重载(统一/上下/四角)
clipviewcompose-ui-contract / com.viewcompose.ui.modifierpublic强制裁剪内容到形状边界全局常与圆角/自绘搭配
alphaviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置透明度全局graphicsLayer.alpha 冲突时后者优先
elevationviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置阴影高度全局映射 View.elevation
zIndexviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置层级偏移全局当前映射 translationZ
graphicsLayerviewcompose-ui-contract / com.viewcompose.ui.modifierpublic统一设置缩放/旋转/平移/裁剪等图层属性全局高级视觉变换入口
visibilityviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置可见性(Visible/Invisible/Gone)全局参与布局占位语义
clickableviewcompose-ui-contract / com.viewcompose.ui.modifierpublic基础点击回调全局与 gesture 分发链协同
focusableviewcompose-ui-contract / com.viewcompose.ui.modifierpublic声明节点可接收焦点全局focusProperties.canFocus 可覆盖
focusRequesterviewcompose-ui-contract / com.viewcompose.ui.modifierpublic将稳定请求器绑定到节点全局节点复用、回滚和释放时自动换绑
focusPropertiesviewcompose-ui-contract / com.viewcompose.ui.modifierpublic声明可聚焦状态与方向目标全局支持 next/previous/四方向
focusGroupviewcompose-ui-contract / com.viewcompose.ui.modifierpublic声明键盘导航焦点组容器映射原生 descendant focus 与 navigation cluster
onFocusChangedviewcompose-ui-contract / com.viewcompose.ui.modifierpublic观察自身/后代焦点状态全局回调 FocusState
onPreviewKeyEventviewcompose-ui-contract / com.viewcompose.ui.modifierpublic焦点目标前的按键捕获阶段全局从声明式祖先向目标分发
onKeyEventviewcompose-ui-contract / com.viewcompose.ui.modifierpublic按键冒泡阶段全局从目标向声明式祖先分发
contentDescriptionviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置无障碍描述全局映射 View.contentDescription
testTagviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置测试标记全局供 UI 测试定位
overlayAnchorviewcompose-ui-contract / com.viewcompose.ui.modifierpublic设置 overlay 锚点 ID指定能力用于 Popup/Tooltip/Dropdown 锚定
drawBehindviewcompose-ui-contract / com.viewcompose.ui.modifierviewcompose-graphics / com.viewcompose.graphicspublic在内容前执行自定义绘制全局两处同名入口;业务侧推荐 com.viewcompose.graphics
drawWithContentviewcompose-ui-contract / com.viewcompose.ui.modifierviewcompose-graphics / com.viewcompose.graphicspublic自定义内容绘制顺序(可调用内容)全局适合混合前景/内容绘制
drawWithCacheviewcompose-ui-contract / com.viewcompose.ui.modifierviewcompose-graphics / com.viewcompose.graphicspublic构建并复用绘制缓存全局用于降低高频重绘成本
drawviewcompose-ui-contract / com.viewcompose.ui.modifierviewcompose-graphics / com.viewcompose.graphicspublicdrawBehind 短写全局语义等价别名
drawCacheviewcompose-ui-contract / com.viewcompose.ui.modifierviewcompose-graphics / com.viewcompose.graphicspublicdrawWithCache 短写全局语义等价别名
dropShadowviewcompose-ui-contract / com.viewcompose.ui.modifierpublic添加单层精确外阴影全局在节点内容前绘制;与 elevation 独立
dropShadowsviewcompose-ui-contract / com.viewcompose.ui.modifierpublic添加有序多层精确外阴影全局同一调用内各层共享显式或节点默认 shape
innerShadowviewcompose-ui-contract / com.viewcompose.ui.modifierpublic添加单层精确内阴影全局在完整内容后绘制,不参与输入分发
innerShadowsviewcompose-ui-contract / com.viewcompose.ui.modifierpublic添加有序多层精确内阴影全局裁切在 shape 内,声明靠后的层后绘制
pointerInputviewcompose-gesture / com.viewcompose.gesturepublic原始指针事件处理入口全局可返回 Consumed 强拦截后续手势
combinedClickableviewcompose-gesture / com.viewcompose.gesturepublic点击/双击/长按组合入口全局无回调时 no-op,不吞事件
draggableviewcompose-gesture / com.viewcompose.gesturepublic连续拖拽手势全局通过 DraggableState 回调位移
anchoredDraggableviewcompose-gesture / com.viewcompose.gesturepublic锚点拖拽/吸附手势全局仅支持 Horizontal/Vertical
transformableviewcompose-gesture / com.viewcompose.gesturepublic多指缩放/旋转/平移全局TransformableState 消费增量
gesturePriorityviewcompose-gesture / com.viewcompose.gesturepublic设置手势优先级全局用于嵌套冲突仲裁
nestedScrollviewcompose-gesture / com.viewcompose.gesturepublic声明父子滚动与 fling 消费协议全局透明宿主接入 AndroidX nested-scrolling 链
animateContentSizeviewcompose-animation / com.viewcompose.animationpublic节点尺寸变化动画全局(布局参与)非视觉缩放,真实参与父布局重排
constrainAsviewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayoutpublicConstraintReference 声明子项约束指定容器ConstraintLayout 子项有效
constrainviewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayoutpublic通过字符串 ID 声明子项约束指定容器constrainAs 的短写风格入口
nativeViewviewcompose-host-android / com.viewcompose.host.androidpublic直接配置底层 Android ViewAndroid interop逃生通道,绕过通用语义层
androidAnimationviewcompose-host-android / com.viewcompose.host.android.animationpublic配置 Android 动画互操作Android interop基于 nativeView 封装别名
androidGraphicsviewcompose-host-android / com.viewcompose.host.android.graphicspublic配置 Android 图形互操作Android interop基于 nativeView 封装别名
resolveviewcompose-renderer / com.viewcompose.renderer.modifierinternal将 modifier 链解析为 ResolvedModifiersrenderer internal框架内部 API,业务侧不可依赖

3.4 Scoped Modifier APIs

API作用域模块/命名空间可见性用途备注生效范围补充说明
weightRowScopeviewcompose-widget-core / com.viewcompose.widget.corepublic设置横向线性布局权重Row 子项RowScope 可用,要求 weight > 0
alignRowScopeviewcompose-widget-core / com.viewcompose.widget.corepublic设置交叉轴(垂直)对齐Row 子项参数 VerticalAlignment
weightColumnScopeviewcompose-widget-core / com.viewcompose.widget.corepublic设置纵向线性布局权重Column 子项ColumnScope 可用,要求 weight > 0
alignColumnScopeviewcompose-widget-core / com.viewcompose.widget.corepublic设置交叉轴(水平)对齐Column 子项参数 HorizontalAlignment
alignBoxScopeviewcompose-widget-core / com.viewcompose.widget.corepublic设置子项在 Box 内对齐Box 子项参数 BoxAlignment
constrainAs / constrainConstraintLayout 子项上下文viewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayoutpublic声明子项约束 parent-dataConstraintLayout 子项入口是全局 Modifier 扩展,但语义仅在 ConstraintLayout 生效

3.5 高级阴影示例与约束

val cardShape = UiShape.rounded(20.dp)

Surface(
modifier = Modifier
.shape(cardShape)
.dropShadows(
shadows = listOf(
UiShadow(
color = 0x33000000,
blurRadius = 12.dp,
offsetY = 5.dp,
),
UiShadow(
color = 0x223B82F6,
blurRadius = 18.dp,
spreadRadius = 2.dp,
offsetX = (-4).dp,
),
),
shape = cardShape,
),
) {
Content()
}
  1. 要求像素级 blur/spread/offset/color 或多层合成时使用 dropShadow(s);Material 高程语义继续使用 elevation
  2. 需要稳定轮廓时推荐同时为内容和阴影传入同一个 UiShape;未显式传入时使用节点 shape/cornerRadius,再回退矩形。
  3. 阴影不扩张布局 bounds。外阴影需要调用侧保留视觉空间,并避免在非 viewport 祖先上启用不必要裁切。
  4. 高频动画优先变换节点的 translation/scale/rotation/alpha;逐帧动画 blur、spread、shape 或尺寸会产生新的栅格 key。
  5. 完整后端、缓存和诊断规则见 shadows.md

3.5 一致性校验(扫描对照)

  1. 本文档已覆盖扫描得到的全部 fun Modifier.*(含 internal)。
  2. scoped 能力与 global 能力已分表,不混用统计口径。
  3. 重复语义入口(draw*ui-contractgraphics)已注明推荐命名空间。

4. 角色边界

4.1 Modifier(通用外层修饰)

适合放入 Modifier 的能力:

  1. 尺寸与占位:size/width/height/minWidth/minHeight/padding/margin
  2. 外观修饰:backgroundColor/backgroundDrawableRes/border/cornerRadius/alpha/elevation
  3. 可见性与层级:visibility/offset/zIndex
  4. 通用交互与可访问性:clickable/focusable/focusRequester/focusProperties/focusGroup/onFocusChanged/onPreviewKeyEvent/onKeyEvent/contentDescription
  5. 测试定位:testTag
  6. 系统栏内边距:systemBarsInsetsPadding
  7. 软键盘内边距:imeInsetsPadding
  8. 逃生通道:nativeView(key, configure)
  9. 列表性能策略:容器参数 reusePolicy/motionPolicy
  10. 容器输入跟随策略:垂直容器参数 focusFollowKeyboard
  11. 内容尺寸过渡:animateContentSize(animationSpec)(对节点尺寸变化做布局级动画,spec 语义透传到执行层)
  12. 图形绘制阶段:drawBehind/drawWithContent/drawWithCache(用于自定义绘制与缓存命令)

4.2 Scoped Modifier(父容器相关 parent-data)

只在特定父容器内成立的能力,通过作用域暴露:

  1. RowScope.weight
  2. RowScope.align
  3. ColumnScope.weight
  4. ColumnScope.align
  5. BoxScope.align
  6. ConstraintLayout 子项约束 parent-data:layoutId/constrainAs/constrain

4.3 NodeSpec(组件语义)

组件自身语义进入组件参数与 NodeSpec,例如:

  1. Textcolor/style/maxLines/overflow/textAlign
  2. ImagecontentScale/tint/placeholder/error/fallback
  3. Buttonvariant/size/enabled/leadingIcon/trailingIcon
  4. TextFieldlabel/placeholder/supportingText/readOnly/imeAction/isError

4.4 Theme / Defaults(默认值来源)

默认值链路固定为:

Theme -> Defaults -> NodeSpec -> Renderer

约束:

  1. 不把主题默认值直接编码为通用 Modifier
  2. 不在 renderer 写组件业务默认值

5. 新能力落点判断

新增一个属性时,按顺序判断:

  1. 是否对大多数节点都稳定成立的外层修饰?
  2. 是否父容器相关的布局数据?
  3. 是否某个组件自身语义?
  4. 是否默认值来源(主题/默认样式)?

命中哪一类,就落到对应层,不跨层混放。

6. 反模式清单

  1. 在通用 Modifier 新增组件专属语义字段
  2. 在全局 Modifier 暴露父容器特定能力
  3. 为了快速接入把第一方长期语义回流到动态 map
  4. 把主题覆盖当作组件参数替代方案

7. Compose 对齐原则

ViewCompose 不复刻 Compose runtime/compiler,但在 API 分层上保持对齐:

  1. Modifier = 通用修饰链
  2. parent-data = scope API
  3. 组件语义 = 参数/NodeSpec
  4. 主题 = 默认值来源

8. 变更门禁

涉及 Modifier 边界变化时,至少完成:

  1. 本文档同步
  2. 对应 NodeSpec/renderer 路径回归
  3. demo 验证与必要 UI 测试

流程规则见 workflow.md

9. 关联文档

  1. node-spec.md
  2. theming.md
  3. overview.md
  4. focus-and-input.md
  5. nested-scroll.md