R1.15.4persisted user theme设计

用户选定的主题需跨会话保持并即时生效

别名: 主题持久化 · 即时切主题 · theme persistence · session-stable theme

概念解释

用户选定的主题(含明暗、对比、密度,以及他们打开过的组合)必须写进跨会话仍在的存储,下次打开应用时在第一次绘制之前读回;切换时必须在当前页立刻重绘,不能靠整页刷新、不能把滚动位置和焦点丢掉,也不能只在「下次启动」才变。保持失败等于每次访问都把人推回默认,等于没给选择。延迟生效等于让人无法确认「我刚刚选的是不是这个」,于是反复开关,或以为坏了。

选定是用户的,不是设备的当前外观自动值。系统外观可以当缺省,一旦用户显式选过,显式选择优先,并且这份选择要跟着账号或至少跟着这台设备上的这个应用走。

机制

绘制若在读存储之前就开始,第一帧会闪回默认,再跳到用户的选择。闪的那一帧足以让人以为应用「又重置了」,也会在深色环境里闪出一块白。所以读必须发生在首次绘制之前:阻塞启动里的同步读,或在绘制前就把类名打在根节点上。

即时生效要求主题是运行时可替换的表,而不是构建期烘焙进每个页面的静态类。整页刷新能换表,但会拆掉滚动、焦点、未提交的表单,把一次外观决定变成一次导航。局部重绘只替换语义取值,树和状态机不动,选择才能在当场被看见、被相信。存储若只写在内存里,关标签即丢;若写在无法跨设备的本地而产品承诺账号级,换机器又丢。丢的表现都是「我设过,它不认」。

边界

无存储的隐私模式或被禁用存储的环境,无法跨会话保持,应在当次会话内仍即时生效,并在设置里说明「这次关闭后不会记住」。服务端渲染的第一帧若拿不到用户选择,需要在根节点用内联脚本在绘制前写入,而不是等水合之后再闪。主题选择若被组织策略锁死(企业只允许高对比),用户设定应显示为只读并解释来源,不要提供一个按了却被策略盖掉的开关。动画过长的全屏过渡会让「即时」变成表演,选择的确认被拖到过渡结束——过渡必须短到仍能当场核对,或提供跳过。

怎么落地

  • 在首次绘制前从持久存储读出用户选择并打在根上;没有显式选择时才回落到系统外观。显式选择一旦发生,写入存储并覆盖缺省。
  • 切换时只替换语义表并重绘当前树,禁止为换主题做一次路由级刷新。保存滚动位置与焦点。
  • 账号级产品把选择同步到服务端,登录后的第一帧使用账号值;本地与服务端冲突时以更新的那次用户操作为准。
  • 验证:选高对比紧凑,杀掉应用再打开,第一帧就必须是该组合,不允许先闪标准浅色。在长列表中间打开设置切明暗:列表位置与当前焦点应还在,画面在不到一秒内换完。清掉存储再打开,应回到系统缺省;再选一次、换设备登录,账号级产品应带上那次选择。任何一条失败,保持或即时至少坏了一头。

延伸

  • 同组R1.15.1 多品牌共用结构,只替换语义层取值 · R1.15.2 品牌数量增加时验证成本按品牌乘状态增长 · R1.15.3 主题不只有明暗,还包括对比度与密度
  • 相邻R1.01 设计令牌 · R1.06 贡献流程与治理
  • 站内检索persisted user theme · theme persistence · flash of incorrect theme

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/R1.15.4