尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Folo(Follow)移动端 v0.2.5 更新详解:文章内容独立字号与预设档位的实现剖析

Folo(Follow)移动端 v0.2.5 更新详解:文章内容独立字号与预设档位的实现剖析 FoloFollow移动端 v0.2.5 更新详解文章内容独立字号与预设档位的实现剖析本文聚焦 FoloFollow移动端 v0.2.5 发布说明见 apps/mobile/changelog/0.2.5.md中的核心新增能力为文章正文设置独立于界面字号的字体大小并提供多档预设同时梳理该版本针对特定场景下无法订阅 Feed通知打开的条目无法加载两项缺陷的修复。通过逐行对照移动端 UI 设置原子、外观设置界面与 WebView 渲染通道的源码读者将理解 Folo 移动端界面字号 / 内容字号双轨缩放机制的完整设计、实现路径与配置方式可直接在「设置 → 外观 → 字体缩放」中复现并调优。版本快照v0.2.5 改了什么依据官方变更日志v0.2.5 的内容可分为三类新功能Shiny new things新增独立的文章内容字体大小选项及预设档位Add option for independent content font size and presets。改进Improvements无显式条目。缺陷修复No longer broken修复特定场景下无法关注/订阅 Feedfollow the feed的问题修复从系统通知打开条目entries opened from notifications时无法加载的问题。其中真正具备完整新增能力 用户可配置入口 底层实现闭环的是第一条。它对应的用户入口位于「设置 → 外观Appearance→ 字体缩放」本节将基于 外观设置界面 及其依赖的原子状态与渲染通道逐层展开。功能入口外观设置里的字体缩放设置组在移动端「外观」设置页中字体缩放作为一个独立分组appearance.font_scaling.title提供四个联动开关/选择器其 UI 渲染位于 Appearance.tsx设置项类型默认值说明使用系统字体缩放useSystemFontScalingSwitchtrue跟随系统无障碍字号详见 默认值定义字体缩放比例fontScaleSelect1m / 默认关闭系统缩放后以倍数形式调节全局界面与内容字号内容使用独立字体大小useDifferentFontSizeForContentSwitchfalse打开后正文内容不再跟随全局缩放而使用独立的像素档位内容字体大小mobileContentFontSizeSelect16m / 中号仅在上一个开关开启时显示设置文章正文的绝对字号设置状态全部落在一个名为ui的设置原子中。Folo 移动端在继承共享端UISettings的基础上扩展了四个字段见 apps/mobile/src/atoms/settings/ui.ts#L8-L13export interface UISettings extends BaseUISettings { fontScale: number useSystemFontScaling: boolean useDifferentFontSizeForContent: boolean mobileContentFontSize: number }对应的出厂默认值分别为fontScale: 1、useSystemFontScaling: true、useDifferentFontSizeForContent: false、mobileContentFontSize: 16。也就是说开箱即用的字号体验完全跟随系统无障碍缩放需要手动关闭系统缩放后才能看到字体缩放比例档位再额外打开内容使用独立字体大小正文才会进入独立像素档位模式。这一默认取向与无障碍优先的设计一致。值得注意的细节是服务端同步白名单apps/mobile/src/atoms/settings/ui.ts#L36-L43fontScale与useSystemFontScaling会被同步到服务端而移动端新增的useDifferentFontSizeForContent与mobileContentFontSize属于纯本地偏好不在同步列表内。两套预设档位倍数缩放 vs 绝对像素v0.2.5 引入的presets预设不是一套而是两套并存这在源码中定义得非常明确Appearance.tsx① 全局字体缩放预设倍率制const fontSizePresets [ { value: 0.8, key: xs }, { value: 0.9, key: s }, { value: 1, key: m }, { value: 1.2, key: l }, { value: 1.5, key: xl }, ] as constkey中文标签缩放倍率xs较小×0.8s小×0.9m默认×1.0l大×1.2xl较大×1.5② 文章内容字号预设像素制// Content font size presets (in px) const contentFontSizePresets [ { value: 12, key: xs }, { value: 14, key: s }, { value: 16, key: m }, { value: 18, key: l }, { value: 20, key: xl }, ] as constkey中文标签字号pxxs极小号12s小号14m中号16l大号18xl特大号20两套档位的差异是理解该功能的关键界面缩放是相对倍率作用于排版 token 全家桶内容字号是绝对像素直接注入条目渲染 WebView 的根字号。档位的中英文标签可在 locales/settings/zh-CN.json 中找到如appearance.font_scaling.content_size.m→ 中号。界面层实现FontScalingProvider 与排版 token 缩放当用户通过字体缩放比例选择档位后这个倍率如何作用到整个 App 的文字答案在 FontScalingProvider.tsx 中它以 Provider 形式包裹整个视图树根据全局设置计算出一组 CSS 变量并注入到容器View的 NativeWindvars()中const createFontScalingInjectStyles (scale 1) { const cssVars Object.entries(typography).reduce((acc, [key, [fontSize, lineHeight]]) { const kebabKey key.replaceAll(/([A-Z])/g, -$1).toLowerCase() const nextFontSize Math.round(fontSize * scale) const originalRatio lineHeight / fontSize // 小字号行高至少 1.2 倍字号大字号至少 1.0 倍保证可读性 const minRatio fontSize 36 ? 1 : 1.2 const scaledLineHeight Math.round( Math.max(nextFontSize * Math.max(originalRatio, minRatio), lineHeight * scale), ) acc[--text-${kebabKey}] nextFontSize acc[--text-${kebabKey}-line-height] scaledLineHeight return acc }, {} as Recordstring, number) return vars(cssVars) as StylePropViewStyle }该实现有两个值得深挖的设计点字体与行高同步缩放遍历typography排版规范中的每一组[fontSize, lineHeight]分别按倍率换算成--text-{key}与--text-{key}-line-height两个 CSS 变量保证缩放后行高与字号仍成比例行高下限保护通过minRatio兜底——小字号下行高至少保持字号的 1.2 倍、超大字号≥36也至少 1.0 倍避免极小/极大字号场景出现行距塌陷与系统缩放的联动Provider 在组装样式时执行systemFontScaling ? 1 : fontScaleFontScalingProvider.tsx#L35-L38即当使用系统字体缩放开启时不叠加自绘的倍率样式把字号控制权完全交给系统。内容层实现条目 WebView 的根字号注入界面布局走 NativeWind CSS 变量而文章正文并不在 RN 原生层渲染——它由一套独立的 HTML 渲染器web-app/html-renderer目录在 WebView 中展示。因此内容独立字号必须打通一条从设置原子到 WebView 的通道。在条目渲染 Hook useWebViewEntry 中可以看到两条相互配合的生效逻辑// ① 全局字号跟随系统时取 PixelRatio.getFontScale()否则用自定义倍率 useEffect(() { const fontScale useSystemFontScaling ? PixelRatio.getFontScale() : customFontScale WebViewManager.setRootFontSize(fontScale * 16) }, [useSystemFontScaling, customFontScale]) // ② 独立内容字号开启后直接注入移动端内容字号绝对 px useEffect(() { if (useDifferentFontSizeForContent) { WebViewManager.setRootFontSize(mobileContentFontSize) } else { const fontScale useSystemFontScaling ? PixelRatio.getFontScale() : customFontScale WebViewManager.setRootFontSize(fontScale * 16) } }, [useDifferentFontSizeForContent, mobileContentFontSize, useSystemFontScaling, customFontScale])机制解读默认状态useDifferentFontSizeForContent false下WebView 根字号 fontScale × 16跟随系统时用 React Native 的PixelRatio.getFontScale()拿到系统无障碍倍率关闭系统缩放后则使用用户在fontScale档位中选的倍率0.81.5乘上 16px 基准开启内容使用独立字体大小后第二段 Effect 立即接管不再计算倍率而是把mobileContentFontSize的绝对像素值1220px直接设为 WebView 根字号——这正是 v0.2.5为正文内容提供独立且带预设的含义。最终下发动作位于 webview-manager.tssetRootFontSize(size 16): void { SharedWebViewModule.dispatch?.(setRootFontSize, JSON.stringify(size)) }它通过原生桥接模块向共享 WebView 实例发送setRootFontSize消息HTML 渲染器据此调整其 CSS 根字号rem基准从而让整篇文章的排版随单一值整体缩放。原生渲染列表、导航等界面文字由FontScalingProvider负责、WebView 内正文由setRootFontSize负责两条链路各司其职、互不干扰——这正是独立内容字号在架构上成立的前提。操作路径与调参建议要把 v0.2.5 的新能力用起来可按以下路径操作移动端「设置 → 外观」内纯跟随系统默认保持「使用系统字体缩放」开启即可系统无障碍字号越大 App 越大无需额外设置全局倍率微调关闭「使用系统字体缩放」在「字体缩放」档位中选择 ×0.8×1.5。该档位会同时影响界面与正文正文走倍率 × 16正文单独调整在上述基础上开启「内容使用独立字体大小」随后在「内容字体大小」中选择 12/14/16/18/20px 五档预设。此时界面对话列表的字号不再影响正文反之亦然恢复默认将「内容使用独立字体大小」关闭并把「字体缩放」切回默认×1.0。从源码可推断的组合边界是mobileContentFontSize选择器仅在useDifferentFontSizeForContent为真时才渲染Appearance.tsx#L206-L223因此不存在开关关闭却仍显示像素档位的歧义状态。同版本的两项缺陷修复v0.2.5 同时合入了两项修复官方变更日志的描述如下修复特定场景下无法关注 Feed涉及订阅follow/subscribe流程在特定输入与网络组合下失败的健壮性修复保证 Feed 能被成功加入订阅列表修复从通知打开的条目无法加载涉及通知深链deep link跳转后条目内容初始化失败的问题修复后用户点击推送可直接进入对应条目阅读页。由于二者属于回归性修复而非功能新增changelog 记录较为精简若需排查或回滚验证可关注订阅列表模块与通知/深链初始化路径的测试用例与提交记录。其验证成本较低分别尝试从搜索/发现页关注多种类型 Feed、以及在收到推送后点击通知打开条目即可复现原问题是否消除。小结v0.2.5 是 Folo 移动端在阅读排版可访问性上的一次重要迭代。它引入的并非单纯的加个大字号选项而是一套双轨字号体系界面层通过 FontScalingProvider 按倍率缩放排版 token内容层通过 useWebViewEntry 把独立像素档位注入条目 WebView 根字号两层又都受ui设置原子的三个开关系统缩放 / 倍率档位 / 独立内容字号约束最终以清晰的分组呈现在「外观 → 字体缩放」中。对于开发者围绕本功能可继续阅读的关键文件包括设置定义 ui.ts、预设与 UI Appearance.tsx、缩放注入 FontScalingProvider.tsx、WebView 下发 hooks.ts 与 webview-manager.ts。若需扩展新档位例如更大的 ×2.0 或 24px只需同步修改Appearance.tsx中的两套presets数组与对应的 中文文案档位键 即可其他渲染通道会自动适配。创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表