移动/游戏
用 Jetpack Compose Glimmer…
当需要为 Android XR 显示眼镜构建投影式(Projected Activity)Glimmer UI 时,按此流程搭建依赖、主题、组件与交互。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
用 Jetpack Compose Gl特定
解决思路
- 创建 Projected Activity:若项目尚无,先新建一个投影 Activity,并在 app manifest 中为该 Activity 的 android:requiredDisplayCategory 指定 xr_projected,告知系统该 Activity 通过投影上下文访问已连接设备硬件;用 references/projectedcontext-source.md 在投影设备上启动该 Glasses Activity。
- 移动端集成:若已有手机 App,必须新建一个专门渲染 Glimmer UI 的 Glasses Activity;若尚无启动方式,在手机 UI 上加一个“Launch on Glasses”按钮,用 ProjectedContext 在眼镜上启动该 Activity,并把按钮放在屏幕级 FloatingActionButton、TopAppBar 或顶部导航栏以保证可发现性;眼镜未连接时禁用该按钮;绝不在手机上启动 Glasses Activity,只投到显示眼镜;若业务上适合自动启动,则无需显式按钮直接启动。
- 添加 UI 库:检查项目是否已有 androidx.xr.glimmer:glimmer,没有则按官方“Declaring Jetpack Compose Glimmer Dependencies”引入最新版本。
- 主题包裹:所有 Glimmer 组件必须包在 GlimmerTheme composable 内,以保证 token 正确解析。
- 强制纯黑背景:显示眼镜是加色(additive)显示,任何非黑背景都会遮挡现实世界;必须在 Projected Activity 根容器上设置 Modifier.background(Color.Black)。
- 字体:默认使用 Google Sans Flex,引入 androidx.xr.glimmer.googlefonts,用 createGoogleSansFlexTypography 创建 Typography 实例并通过 GlimmerTheme 传入;除非明确指定品牌字体,否则一律使用默认字型。
- 运行时检查硬件能力:不同类型智能眼镜能力不同,按官方“Check device capabilities at runtime for intelligent eyewear”在运行时检测。
- 申请硬件权限:麦克风、摄像头等权限按官方“Request hardware permissions for intelligent eyewear”申请。
- 访问硬件:使用眼镜摄像头、传感器或手机硬件时,按官方“Use a projected context to access hardware on intelligent eyewear”通过投影上下文访问。
- 用 Glimmer 组件构建 UI:显示眼镜界面一律使用 Jetpack Compose Glimmer 框架组件。
- 用深度表达层级:通过深度(depth)传达元素优先级与层次。
- 自下而上设计:尽量少遮挡现实世界,UI 始终底部对齐眼镜显示区域。
- 一次只显示一件事:优先保证用户对现实世界的感知,同一时刻只显示一个主要信息(例如用 Stack),避免多张卡片同时出现。
- 颜色对比:前景与背景在 HCT 色彩空间中至少保持 70% 色调差(计算方式见 references/material-hct-source.md)。
- 映射输入控件:把点击、滑动等交互映射到眼镜可用硬件控件(如触控板)。
- 输入是一维的:用户一次只能做一个控制输入。
- 避免嵌套滚动控件。
- Glimmer 组件默认兼容标准输入方式(触控板点击/滑动)。
- 用系统返回键关闭临时状态或详情视图。
- 添加输入、焦点、点击、滑动时参考官方“Focus in Jetpack Compose Glimmer”文档;硬件输入细节见“Hardware Controls for display glasses”。
- 焦点管理:Glimmer 使用一维焦点搜索;可滚动容器中焦点连续移动,按钮行等元素中焦点离散移动;必须在 Activity 的 onCreate 中把 isInitialFocusOnFocusableAvailable 设为 true,让系统自动设置初始焦点。
- 样式通过 GlimmerTheme 对象访问(参考 references/glimmertheme-source.md):颜色 primary #9BBFFF、secondary #4C88E9、surface #262626(透明基底,渲染为透明)、outline #606460(3.dp 边框);形状 Standard 为 RoundedCornerShape(36.dp)、Small 为 RoundedCornerShape(12.dp)。
- 排版:默认必须使用 Google Sans Flex(除非明确指定品牌字体);作为可变字体需配置轴:Roundness(ROND)=100f、Width(wdth)=100f、Optical Size(opsz)=9f、Weight(wght) 按角色取值(Title 725f、Body 520f、Caption 650f);字号/行高:Title Large 30sp/36sp、Title Medium 24sp/32sp、Title Small 20sp/28sp、Body Large 30sp/36sp、Body Medium 24sp/32sp、Body Small 20sp/28sp、Caption 18sp/28sp。
- 深度层级:用阴影模拟深度建立层级,Glimmer 控件使用 DepthEffect 的 5 个预设 DepthEffectLevels(参考 deptheffect-source.md 与 deptheffectlevels-source.md);level1 用于卡片和常驻背景 UI 的静止态,level2 用于按钮和可交互卡片的聚焦/按下态,ExtraSmall 为 4.dp。
- 卡片(Card):作为基础表面容器把相关内容聚为一个焦点,建立清晰深度平面;不要在 ListItem 内嵌卡片;若整张卡片是单一触发点(如媒体项、设置项)则提供 onClick 以启用焦点反馈;若卡片内含多个独立交互元素(按钮、开关)则 onClick 传 null 以避免焦点冲突;参考 cards.md、card-source.md、card-samples-source.md。
- 按钮(Button):作为离散动作的主要触发器,针对眼镜焦点模型优化;标准按钮(必带文字标签,可选前后图标)用于空间充足或含义不明确时;图标按钮仅在图标含义清晰时使用;两者都有默认(单一动作如购买、导航)和切换(有选中态如静音)变体;参考 buttons.md、button-source.md、button-samples-source.md。
- 标题芯片(Title Chip):胶囊形标签组件,放在 Card 或内容组上方作标题,显示短标题、名称或状态;独立 TitleChip 前置内容时必须使用 TitleChipDefaults.AssociatedContentSpacing(8.dp)保持视觉层级;纯信息性,不可聚焦或激活导航;文字始终居中、不得换行、超出截断,标签不超过三个词;参考 title-chips.md、titlechip-source.md、titlechip-samples-source.md。
- 图标(Icon):用预定义 IconSizes(如 Standard、Large)保证可读性并满足 XR 最小点击目标;若图标是触发器必须用 IconButton 以获得自动视觉反馈和必要点击内边距,否则用独立 Icon 作非交互指示;绝不用纯黑 #000000 作图标着色,始终用主题色或标准 Glimmer 内容色;默认图标库为 Material Symbols(600 字重、Rounded、Unfilled);参考 icons.md、icon-source.md、iconbutton-source.md、iconsizes-source.md。
- 列表(List):用于在眼镜上浏览多个条目;若一次只看一个条目则改用 Glimmer Stack;条目类型相似时用列表并配 Title Chip,类型不同时用 Stack;行用 ListItem composable 的预定义槽位;相似条目列表保持一致的背景色(通常 GlimmerTheme.colors.surface)和圆角(标准 36.dp),除非在视觉上分组不同类型内容;需要列表内分节标题时启用集成 Title Chip 而非独立 TitleChip;GlimmerLazyColumn 必须使用 verticalArrangement = Arrangement.spacedBy(20.dp),条目间距默认 20 dp;参考 list-source.md、listitem-source.md、liststate-source.md。
- 堆叠(Stack):折叠式列表,一次只显示一个内容(如卡片);若需同时显示多个条目则用 List;Stack 不配 Title Chip;条目类型不同用 Stack,类型相同用 List;Stack 接受可变高度条目,底部对齐显示区域;Stack 控件必须比最高条目高 66 dp,为 scrim 留空间并减少切换时的位移;必须在每个 item 块的 Card(或相关容器)上应用 .itemDecoration(CardDefaults.shape) 以保证后方条目被正确裁剪隐藏;用 ShadowScope、DepthEffect 或规定的 DepthEffectLevels 做深度阴影;参考 stack-source.md、stackstate-source.md、stackitemscope-source.md。
- 文本(Text):使用 Glimmer 的 Text 组件并从 GlimmerTheme 选择样式,需要自定义排版时改主题;在透明加色显示上,Material Text 会解析为深色前景 token 而渲染成透明不可见,Glimmer Text 会自动匹配主题色,未手动指定颜色时默认使用最近 Glimmer 表面的内容色;不要用 Material Text,要用 Glimmer Text。
- 表面(Surface):Glimmer 的基础构建块,代表按钮、卡片等组件的独立视觉区域或“物理”边界;构建自定义组件时使用;参考 surface-source.md。
- 系统 UI 集成:通知行为参考官方“Understand notification behavior for intelligent eyewear”,并学习如何从通知在显示眼镜上启动眼镜 Activity。
- 核心约束:不要使用 MaterialTheme 或 Material 组件;要使用 GlimmerTheme 和 Jetpack Compose Glimmer 组件;要用 androidx.xr.glimmer:glimmer-google-fonts 的 createGoogleSansFlexTypography() 作为 GlimmerTheme 的 Typography 值以保证全局排版一致。
- 已知限制:不支持标准 Material 3 阴影或 elevation 修饰符,必须用 ShadowScope 或 Glimmer 的 Depth 令牌;可读文字绝对最小为 18sp(0.6°),更小会不通过可读性检查;避免 Thin/Hairline 字重,它们在加色 AR 镜片上会产生闪烁和锯齿。
- 前置条件:项目 compileSdk 必须为 37 或更高,低于 37 则提升到 37;并使用官方“Create your first activity for intelligent eyewear”中的最新库依赖。
适用边界 · 注意事项
- 不使用 Jetpack Compose Glimmer 或面向手机/平板等非显示眼镜形态的普通 Android UI 场景。
- 项目 compileSdk 低于 37 且无法升级时。
- 不使用 Android XR / 智能眼镜投影设备(无 Projected Device 或非加色显示)的场景。