Modifier Architecture
1. 文档定位
本文档定义 Modifier、组件 NodeSpec、Theme/Defaults 的当前边界。
目标是保证新增能力时落点明确,避免语义混放。
2. 当前基线(2026-07)
- identity 入口统一为
Modifier(Modifier.Empty已移除) - 文本语义类历史 modifier(如
textColor/textSize)已退场 weight/align/FlexibleSpacer仅通过RowScope/ColumnScope/BoxScope暴露- 系统栏/键盘 inset 适配走组件侧
Modifier.systemBarsInsetsPadding(...)与Modifier.imeInsetsPadding(...)(若 Activity 使用adjustResize,通常不再叠加imeInsetsPadding,避免双重位移) - 列表容器策略已收口为容器参数:
reusePolicy(sharePool)与motionPolicy(disableItemAnimator/animateInsert/animateRemove/animateMove/animateChange) - 键盘焦点跟随已收口为垂直容器参数:
focusFollowKeyboard;当前覆盖LazyColumn、LazyVerticalGrid、VerticalPager、ScrollableColumn LazyRow、HorizontalPager、ScrollableRow不暴露focusFollowKeyboard,避免“可调用但无效”的 API 漂移- 背景资源支持
Modifier.backgroundDrawableRes(resId);与backgroundColor同时存在时,drawable 优先;当同时存在cornerRadius时自动裁剪内容,clip()仍可作为通用强制裁剪开关 - 内容尺寸动画支持
Modifier.animateContentSize(...);renderer 会在 patch 前自动插入AnimatedSizeHost,以“真实测量尺寸插值”参与父布局重排(非 graphicsLayer 视觉缩放),并保留AnimationSpec的 easing/spring/keyframes/repeat 语义(含 reverse 终态) - 约束 parent-data 支持
Modifier.layoutId(...)、Modifier.constrainAs(...)、Modifier.constrain(...);仅对ConstraintLayout子节点生效 - 图形绘制 modifier 已接入:
Modifier.drawBehind、Modifier.drawWithContent、Modifier.drawWithCache(以及短写draw/drawCache);执行顺序按 modifier 链稳定,drawWithContent可显式控制内容透传;底层执行保证DrawRoundRect四角半径与Drawable + DrawPaint组合语义不丢失 - 声明式焦点与硬件键盘输入已接入:
focusable/focusRequester/focusProperties/focusGroup/onFocusChanged/onPreviewKeyEvent/onKeyEvent映射原生 View 焦点搜索,并由LocalFocusManager提供会话级移动与清除能力 - 统一嵌套滚动协议已接入:
Modifier.nestedScroll(connection, dispatcher)通过透明宿主映射 AndroidX nested-scrolling parent/child 链,覆盖 pre/post scroll、pre/post fling、Lazy/Pager/普通滚动容器与自定义 drag/transform pan - 高级阴影已接入:
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):
fun Modifier.*声明总数(含重载、含 scoped 内部定义):76fun Modifier.*唯一 API 名称数:62- scoped modifier 声明总数:
5(RowScope/ColumnScope/BoxScope) - renderer internal modifier 扩展:
1(仅内部解析能力)
3.2 分组说明(按架构边界)
ui-contract 通用修饰:平台无关的基础Modifier契约入口。gesture 动作输入:手势 DSL,依赖手势状态对象与策略内核。graphics 绘制:绘制阶段 API(含draw*短写)。graphics 阴影装饰:平台无关阴影规格,由 Android decoration layer 执行。animation 尺寸动画:animateContentSize布局尺寸过渡入口。host-android interop:Android 平台互操作能力(nativeView/android*)。renderer internal 解析/策略:仅 renderer 内部使用,不给业务侧依赖。
3.3 Global Modifier APIs(含 internal)
| API | 模块/命名空间 | 可见性 | 用途备注 | 生效范围 | 补充说明 |
|---|---|---|---|---|---|
padding | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置内容内边距 | 全局 | 3 个重载(all/horizontal+vertical/四边) |
margin | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置外边距(layout params 侧) | 全局 | 3 个重载 |
size | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 同时设置宽高 | 全局 | 固定像素语义(框架单位) |
width | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置宽度 | 全局 | 与父容器布局规则共同生效 |
height | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置高度 | 全局 | 与父容器布局规则共同生效 |
minWidth | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置最小宽度约束 | 全局 | 作用于 View.minimumWidth |
minHeight | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置最小高度约束 | 全局 | 作用于 View.minimumHeight |
fillMaxWidth | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 宽度填充父容器 | 全局 | 语义等价 width(MATCH_PARENT) |
fillMaxHeight | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 高度填充父容器 | 全局 | 语义等价 height(MATCH_PARENT) |
fillMaxSize | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 宽高同时填充父容器 | 全局 | 语义等价 size(MATCH_PARENT, MATCH_PARENT) |
offset | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置平移偏移 | 全局 | 映射 translationX/translationY |
layoutId | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 标记子项布局 ID | 指定容器 | 主要用于 ConstraintLayout 子项匹配 |
systemBarsInsetsPadding | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 应用系统栏 inset 内边距 | 全局(容器感知) | 可按四边开关 |
imeInsetsPadding | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 应用软键盘 inset 内边距 | 全局(容器感知) | 默认仅 bottom=true |
backgroundColor | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置背景色 | 全局 | 与 backgroundDrawableRes 同时存在时优先级较低 |
backgroundDrawableRes | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置 drawable 资源背景 | 全局 | 与 cornerRadius 组合时自动裁剪 |
border | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置边框宽度与颜色 | 全局 | 依赖 surface style 管线渲染 |
cornerRadius | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置圆角半径 | 全局 | 3 个重载(统一/上下/四角) |
clip | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 强制裁剪内容到形状边界 | 全局 | 常与圆角/自绘搭配 |
alpha | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置透明度 | 全局 | 与 graphicsLayer.alpha 冲突时后者优先 |
elevation | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置阴影高度 | 全局 | 映射 View.elevation |
zIndex | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置层级偏移 | 全局 | 当前映射 translationZ |
graphicsLayer | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 统一设置缩放/旋转/平移/裁剪等图层属性 | 全局 | 高级视觉变换入口 |
visibility | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置可见性(Visible/Invisible/Gone) | 全局 | 参与布局占位语义 |
clickable | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 基础点击回调 | 全局 | 与 gesture 分发链协同 |
focusable | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 声明节点可接收焦点 | 全局 | focusProperties.canFocus 可覆盖 |
focusRequester | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 将稳定请求器绑定到节点 | 全局 | 节点复用、回滚和释放时自动换绑 |
focusProperties | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 声明可聚焦状态与方向目标 | 全局 | 支持 next/previous/四方向 |
focusGroup | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 声明键盘导航焦点组 | 容器 | 映射原生 descendant focus 与 navigation cluster |
onFocusChanged | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 观察自身/后代焦点状态 | 全局 | 回调 FocusState |
onPreviewKeyEvent | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 焦点目标前的按键捕获阶段 | 全局 | 从声明式祖先向目标分发 |
onKeyEvent | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 按键冒泡阶段 | 全局 | 从目标向声明式祖先分发 |
contentDescription | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置无障碍描述 | 全局 | 映射 View.contentDescription |
testTag | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置测试标记 | 全局 | 供 UI 测试定位 |
overlayAnchor | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 设置 overlay 锚点 ID | 指定能力 | 用于 Popup/Tooltip/Dropdown 锚定 |
drawBehind | viewcompose-ui-contract / com.viewcompose.ui.modifier、viewcompose-graphics / com.viewcompose.graphics | public | 在内容前执行自定义绘制 | 全局 | 两处同名入口;业务侧推荐 com.viewcompose.graphics |
drawWithContent | viewcompose-ui-contract / com.viewcompose.ui.modifier、viewcompose-graphics / com.viewcompose.graphics | public | 自定义内容绘制顺序(可调用内容) | 全局 | 适合混合前景/内容绘制 |
drawWithCache | viewcompose-ui-contract / com.viewcompose.ui.modifier、viewcompose-graphics / com.viewcompose.graphics | public | 构建并复用绘制缓存 | 全局 | 用于降低高频重绘成本 |
draw | viewcompose-ui-contract / com.viewcompose.ui.modifier、viewcompose-graphics / com.viewcompose.graphics | public | drawBehind 短写 | 全局 | 语义等价别名 |
drawCache | viewcompose-ui-contract / com.viewcompose.ui.modifier、viewcompose-graphics / com.viewcompose.graphics | public | drawWithCache 短写 | 全局 | 语义等价别名 |
dropShadow | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 添加单层精确外阴影 | 全局 | 在节点内容前绘制;与 elevation 独立 |
dropShadows | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 添加有序多层精确外阴影 | 全局 | 同一调用内各层共享显式或节点默认 shape |
innerShadow | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 添加单层精确内阴影 | 全局 | 在完整内容后绘制,不参与输入分发 |
innerShadows | viewcompose-ui-contract / com.viewcompose.ui.modifier | public | 添加有序多层精确内阴影 | 全局 | 裁切在 shape 内,声明靠后的层后绘制 |
pointerInput | viewcompose-gesture / com.viewcompose.gesture | public | 原始指针事件处理入口 | 全局 | 可返回 Consumed 强拦截后续手势 |
combinedClickable | viewcompose-gesture / com.viewcompose.gesture | public | 点击/双击/长按组合入口 | 全局 | 无回调时 no-op,不吞事件 |
draggable | viewcompose-gesture / com.viewcompose.gesture | public | 连续拖拽手势 | 全局 | 通过 DraggableState 回调位移 |
anchoredDraggable | viewcompose-gesture / com.viewcompose.gesture | public | 锚点拖拽/吸附手势 | 全局 | 仅支持 Horizontal/Vertical |
transformable | viewcompose-gesture / com.viewcompose.gesture | public | 多指缩放/旋转/平移 | 全局 | 由 TransformableState 消费增量 |
gesturePriority | viewcompose-gesture / com.viewcompose.gesture | public | 设置手势优先级 | 全局 | 用于嵌套冲突仲裁 |
nestedScroll | viewcompose-gesture / com.viewcompose.gesture | public | 声明父子滚动与 fling 消费协议 | 全局 | 透明宿主接入 AndroidX nested-scrolling 链 |
animateContentSize | viewcompose-animation / com.viewcompose.animation | public | 节点尺寸变化动画 | 全局(布局参与) | 非视觉缩放,真实参与父布局重排 |
constrainAs | viewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayout | public | 按 ConstraintReference 声明子项约束 | 指定容器 | 仅 ConstraintLayout 子项有效 |
constrain | viewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayout | public | 通过字符串 ID 声明子项约束 | 指定容器 | constrainAs 的短写风格入口 |
nativeView | viewcompose-host-android / com.viewcompose.host.android | public | 直接配置底层 Android View | Android interop | 逃生通道,绕过通用语义层 |
androidAnimation | viewcompose-host-android / com.viewcompose.host.android.animation | public | 配置 Android 动画互操作 | Android interop | 基于 nativeView 封装别名 |
androidGraphics | viewcompose-host-android / com.viewcompose.host.android.graphics | public | 配置 Android 图形互操作 | Android interop | 基于 nativeView 封装别名 |
resolve | viewcompose-renderer / com.viewcompose.renderer.modifier | internal | 将 modifier 链解析为 ResolvedModifiers | renderer internal | 框架内部 API,业务侧不可依赖 |
3.4 Scoped Modifier APIs
| API | 作用域 | 模块/命名空间 | 可见性 | 用途备注 | 生效范围 | 补充说明 |
|---|---|---|---|---|---|---|
weight | RowScope | viewcompose-widget-core / com.viewcompose.widget.core | public | 设置横向线性布局权重 | Row 子项 | 仅 RowScope 可用,要求 weight > 0 |
align | RowScope | viewcompose-widget-core / com.viewcompose.widget.core | public | 设置交叉轴(垂直)对齐 | Row 子项 | 参数 VerticalAlignment |
weight | ColumnScope | viewcompose-widget-core / com.viewcompose.widget.core | public | 设置纵向线性布局权重 | Column 子项 | 仅 ColumnScope 可用,要求 weight > 0 |
align | ColumnScope | viewcompose-widget-core / com.viewcompose.widget.core | public | 设置交叉轴(水平)对齐 | Column 子项 | 参数 HorizontalAlignment |
align | BoxScope | viewcompose-widget-core / com.viewcompose.widget.core | public | 设置子项在 Box 内对齐 | Box 子项 | 参数 BoxAlignment |
constrainAs / constrain | ConstraintLayout 子项上下文 | viewcompose-widget-constraintlayout / com.viewcompose.widget.constraintlayout | public | 声明子项约束 parent-data | ConstraintLayout 子项 | 入口是全局 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()
}
- 要求像素级 blur/spread/offset/color 或多层合成时使用
dropShadow(s);Material 高程语义继续使用elevation。 - 需要稳定轮廓时推荐同时为内容和阴影传入同一个
UiShape;未显式传入时使用节点shape/cornerRadius,再回退矩形。 - 阴影不扩张布局 bounds。外阴影需要调用侧保留视觉空间,并避免在非 viewport 祖先上启用不必要裁切。
- 高频动画优先变换节点的 translation/scale/rotation/alpha;逐帧动画 blur、spread、shape 或尺寸会产生新的栅格 key。
- 完整后端、缓存和诊断规则见 shadows.md。
3.5 一致性校验(扫描对照)
- 本文档已覆盖扫描得到的全部
fun Modifier.*(含internal)。 - scoped 能力与 global 能力已分表,不混用统计口径。
- 重复语义入口(
draw*在ui-contract与graphics)已注明推荐命名空间。
4. 角色边界
4.1 Modifier(通用外层修饰)
适合放入 Modifier 的能力:
- 尺寸与占位:
size/width/height/minWidth/minHeight/padding/margin - 外观修饰:
backgroundColor/backgroundDrawableRes/border/cornerRadius/alpha/elevation - 可见性与层级:
visibility/offset/zIndex - 通用交互与可访问性:
clickable/focusable/focusRequester/focusProperties/focusGroup/onFocusChanged/onPreviewKeyEvent/onKeyEvent/contentDescription - 测试定位:
testTag - 系统栏内边距:
systemBarsInsetsPadding - 软键盘内边距:
imeInsetsPadding - 逃生通道:
nativeView(key, configure) - 列表性能策略:容器参数
reusePolicy/motionPolicy - 容器输入跟随策略:垂直容器参数
focusFollowKeyboard - 内容尺寸过渡:
animateContentSize(animationSpec)(对节点尺寸变化做布局级动画,spec 语义透传到执行层) - 图形绘制阶段:
drawBehind/drawWithContent/drawWithCache(用于自定义绘制与缓存命令)
4.2 Scoped Modifier(父容器相关 parent-data)
只在特定父容器内成立的能力,通过作用域暴露:
RowScope.weightRowScope.alignColumnScope.weightColumnScope.alignBoxScope.alignConstraintLayout子项约束 parent-data:layoutId/constrainAs/constrain
4.3 NodeSpec(组件语义)
组件自身语义进入组件参数与 NodeSpec,例如:
Text:color/style/maxLines/overflow/textAlignImage:contentScale/tint/placeholder/error/fallbackButton:variant/size/enabled/leadingIcon/trailingIconTextField:label/placeholder/supportingText/readOnly/imeAction/isError
4.4 Theme / Defaults(默认值来源)
默认值链路固定为:
Theme -> Defaults -> NodeSpec -> Renderer
约束:
- 不把主题默认值直接编码为通用
Modifier - 不在 renderer 写组件业务默认值
5. 新能力落点判断
新增一个属性时,按顺序判断:
- 是否对大多数节点都稳定成立的外层修饰?
- 是否父容器相关的布局数据?
- 是否某个组件自身语义?
- 是否默认值来源(主题/默认样式)?
命中哪一类,就落到对应层,不跨层混放。
6. 反模式清单
- 在通用
Modifier新增组件专属语义字段 - 在全局
Modifier暴露父容器特定能力 - 为了快速接入把第一方长期语义回流到动态 map
- 把主题覆盖当作组件参数替代方案
7. Compose 对齐原则
ViewCompose 不复刻 Compose runtime/compiler,但在 API 分层上保持对齐:
Modifier= 通用修饰链- parent-data = scope API
- 组件语义 = 参数/
NodeSpec - 主题 = 默认值来源
8. 变更门禁
涉及 Modifier 边界变化时,至少完成:
- 本文档同步
- 对应
NodeSpec/renderer路径回归 - demo 验证与必要 UI 测试
流程规则见 workflow.md。