ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Pure Live 弹幕“回到底部“恢复按钮布局边界修复:窄视口与大字号下中英文文案越界的约束审计与测试闭环

Pure Live 弹幕“回到底部“恢复按钮布局边界修复:窄视口与大字号下中英文文案越界的约束审计与测试闭环 音视频直播移动开发【免费下载链接】pure_live纯粹直播:哔哩哔哩/虎牙/斗鱼/快手/抖音/网易cc/YY直播/Twitch直播/SOOP直播/M38自定义源应有尽有。项目地址https://gitcode.com/gh_mirrors/pur/pure_live点击查看免费下载弹幕列表暂停追尾后浮出的回到底部 / N 条新弹幕恢复按钮是 pure_live 直播播放页用户交互矩阵 A4-02 的关键一环。本文以docs/DANMAKU_RESUME_LAYOUT_AUDIT_2026_09_09.md审计为核心完整还原该按钮在 320px 窄视口、2 倍字号等极端条件下的横向越界根因、红测数据、left: 12 右对齐 Align的修复方案与 19/19 定向测试闭环并结合当前仓库源码逐层剖析暂停追尾—累计计数—恢复的完整状态机实现。读完可掌握该布局约束的度量方法、可复现的红/绿测试基线以及不回滚状态机行为的边界控制思路。一、结论与范围一次被精确归类的局部 UI 修订审计结论明确源码提交f35e60576cc92dee86ab390ef3f15148bfad2c20修订了弹幕列表恢复按钮的宽度约束4 个真实本地化 Widget 布局红项转绿四文件19/19定向测试、两文件静态分析analyze全部通过。该修订属于用户操作矩阵 A4-02 的一部分不提升完整原生验收状态——也就是说这是一次有明确边界、不夸大成果的局部修复。同期口径保持一致Android 已归档候选仍为bee143e21664e8222b8edabab6aa5ea7d5a87850不含本次 UI 修订Windows 候选仍为f3de664a全平台 3.2.0 正式交付继续按完整目标暂缓。本轮没有进行构建、安装、发布或操作手机全部验证停留在 Widget 测试与静态分析层面这为后续实机验收留下了清晰的工作项见第七节。二、根因定位约束缺失而非计数或状态机故障2.1 基线布局缺陷基线提交bea90e963f822efc23d2302e0c7b22884b65c0b4中DanmakuListView在暂停追尾后显示恢复按钮使用的是Positioned(right: 12, bottom: 12)该写法只锚定右、下两个方向没有横向宽度上限。当新消息累计数的中英文长文案如{count} 条新弹幕点击回到底部、{count} new messages - tap to resume在窄视口或系统大字号下渲染时按钮自然向左无限伸展左侧越出列表边界后被父级ClipRRect裁剪。2.2 第一错误与分类审计特别强调第一处错误是布局约束不是消息计数也不是恢复状态机——这避免了把正常功能误判为故障。按分类体系该缺陷被归类为upstream-existing冻结上游c6c9bd70aedc503c003110dae10a83ad0bb891d8存在相同布局blame 定位到的ed8011b6为其祖先退出 0merge base 为527fea1b40885e3621d53c9646b523dd8522290c。本次仅做本地局部修订没有合并或同步上游为后续回滚保留了独立路径。三、红测复现四组真实本地化数据的越界证据3.1 测试构造方法新测试的复现路径非常贴近生产加载实际的zh/enJSON 本地化资源对应assets/translations/zh.json与assets/translations/en.json挂载生产DanmakuListViewWidget真实拖动滚动暂停追尾从 60 条历史追加 137 条消息断言冻结行保留、最新行未显示、完整计数文案存在并测量按钮左边界。测量使用Flutter Widget 测试字体/坐标不是实机像素或截图结论——这是理解全部数值的前提。3.2 红测数据以下四组按钮左边界均小于要求的8即越出可接受范围语言 / Widget 视口宽 / 字号比例旧按钮左边界en / 320 / 1-197.20001220703125en / 320 / 2-641.2000122070312zh / 320 / 2-163.50003051757812en / 900 / 2-71.70001220703125解读要点320px 视口 1 倍字号英文按钮左侧已越出约 197px接近整个窄视口的一半宽度320px 视口 2 倍字号英文越界达到 -641px远超视口本身文案几乎完全不可见中文 2 倍字号越界 -163px中文文案同样溢出900px 视口 2 倍字号宽视口下大字号仍会越界 -71px证明问题并非窄屏专属字号放大本身就是触发条件。3.3 红测结果的正确定义审计将红测结果明确记录为1 通过、4 布局失败独立的冻结、一次恢复、再次暂停后新计数流程在旧实现下已通过。也就是说正常状态机行为没有被描述为故障失败被严格限定在布局约束范围内。四、修复方案left: 12 右对齐Align的约束设计4.1 修复代码当前仓库已合入在当前仓库 danmaku_list_view.dart 中恢复按钮的挂载方式为if (userScrolling) Positioned( left: 12, right: 12, bottom: 12, // Bound long localized labels without stretching a // short desktop action or reducing the users font. child: Align( alignment: Alignment.centerRight, child: FilledButton.icon( key: const ValueKey(danmaku-resume-live), style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.92), foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)), ), icon: const Icon(Icons.arrow_downward_rounded, size: 18), label: ValueListenableBuilderint( valueListenable: _pendingMessageCount, builder: (context, count, _) Text( count 0 ? i18n(danmaku_new_messages, args: {count: $count}) : i18n(scroll_to_bottom), style: const TextStyle(fontWeight: FontWeight.w600), ), ), onPressed: _resumeAutoScroll, ), ), ),设计要点left: 12与right: 12、bottom: 12构成三边约束把按钮限制在列表可视区域内侧长文案在有限宽度内自动换行不再越界Align(alignment: Alignment.centerRight)让短文案如桌面端Scroll to bottom仍保持紧凑宽度并右对齐不会因left/right双约束被拉伸成通栏按钮也不会缩小用户字号唯一显式恢复入口onPressed: _resumeAutoScroll保持不变字号、完整计数文案、按钮样式均未改动。4.2 明确未改动的边界审计逐项列出本次修订没有触碰的部分防止回归扩散历史上限_maxDanmakuHistory 500冻结快照暂停时的_visibleMessages行为消息去重与DanmakuArrivalCounterTimer节流逻辑PiP 呈现恢复danmakuPresentationRevision监听播放器与网络控制器。五、绿测闭环19/19 定向测试与相邻回归5.1 四组测试的断言升级绿测对原有四组红测断言做了如下核对与加强左右及底部边界均在要求范围内按钮高度至少48满足可点击性命中测试hit test可正确命中断言区域真实点击后最新尾行可见、按钮消失、追尾恢复。此外独立的桌面普通字号用例核对短按钮不拉满不被双约束撑成通栏、第二次拖动后的计数从 1 开始而非累计上次遗留值。5.2 滚动偏移不变断言与相邻回归绿测还加强了新消息到达时滚动偏移不变的断言即暂停冻结期间新消息只累计数量、不移动视口四个原红项的左边界断言按原样保留作为防回归锚点。相邻的滚动策略、到达计数、冻结屏蔽三个文件同步回归全部通过。5.3 隔离性与资源回收隔离夹具无真实账号、网络或播放器卸载unmount后关闭流StreamSubscription与临时 Hive既有 frozen-filter 测试的未加载文案警告保留不误报为失败新增布局用例改用真实双语资源测试及分析退出码均为 0。六、源码级纵深恢复按钮背后的完整状态机修复只是冰山一角。按钮之所以只在该出现时出现、计数只在该累计时累计依赖DanmakuListView与控制器之间一整套协作机制以下全部来自当前仓库源码。6.1 暂停追尾与代币守卫danmaku_list_view.dart 中的DanmakuTailFollowGuard用递增 revision 代币让过期的追尾跳转失效class DanmakuTailFollowGuard { int _revision 0; int capture() _revision; int invalidate() _revision; bool isCurrent(int revision) revision _revision; }其背景是ScrollController.jumpTo会取消进行中的拖拽而消息投递可能在下一帧排队一次 jump——即使手指已经开始滑动过期回调也会被代币判定为 no-op。指针按下onPointerDown时立即invalidate()在 touch slop 产生首个ScrollStartNotification之前就取消排队中的跳转。6.2 暂停时的计数只增不移核心在_onMessagesChanged()danmaku_list_view.dart当_autoScrollEnabled false时新消息只累计到_pendingMessageCount.clamp(0, 9999)封顶不触碰冻结的_visibleMessages快照因此滚动偏移保持不变。节流Timer固定为 80msthrottleDuration暂停期间该 Timer 会被取消。6.3 到达计数器的身份比较danmaku_arrival_counter.dart 的DanmakuArrivalCounter以对象身份HashSet.identity()比较前后快照只保留当前受控历史集合不建立会话级无限去重集合int update(ListT messages) { final next HashSetT.identity()..addAll(messages); final added next.where((message) !_previous.contains(message)).length; _previous next; return added; }这正是 列表累计数审计 中修复的成果满 500 条后新到 3 条长度不变、屏蔽尾行导致尾部变化误判等问题都由身份比较 只保留当前快照解决。内容相同的独立弹幕仍分别计数不按文本去重。6.4 控制器侧的批处理与历史上限消息从平台进入列表要经过 live_play_controller.dart 的常量约束_maxDanmakuHistory 500列表历史上限_maxPendingDanmakuBatch 200待刷批缓冲上限超限丢弃最早消息_danmakuBatchWindow 64ms批量刷出窗口。addDanmakuMessage先进入_pendingDanmakuMessages由Timer(_danmakuBatchWindow, ...)触发_flushDanmakuMessages合并进danmakuMessagesRxList第 62 行removeDanmakuWhere第 538-543 行同时向_danmakuRemovals广播 predicate——暂停冻结的行只删匹配项不替换其他冻结行、不触发恢复追尾。6.5 平台差异与 PiP 呈现恢复桌面滚轮isDanmakuUserScrollStart第 21-31 行在桌面端接受 direction-only 的UserScrollNotification因为鼠标滚轮没有DragDetails移动端必须hasActivePointer才判定为用户滚动避免系统 PiP 的 detach/attach 伪通知误暂停追尾PlatformUtils.isDesktop定义见 platform_utils.dartPiP 恢复竖屏 PiP 时LivePlayContent会以 PiP surface 替换整个竖屏子树live_play_content.dart本 State 通常先 dispose 再重建。因此恢复追尾不靠推断过渡而是监听持久房间控制器的danmakuPresentationRevisionlive_play_controller.dart并在首帧 post-frame 调度_scheduleLiveTailRestore同时赢得与合成视口通知的竞争全屏隐藏系统全屏/窗口全屏下_buildDanmaku()返回SizedBox.shrink按钮随列表一起消失live_play_content.dart。6.6 文案资源与渲染细节按钮文案来自真实双语资源assets/translations/en.jsonscroll_to_bottom: Scroll to bottom第 1564 行danmaku_new_messages: {count} new messages - tap to resumeassets/translations/zh.jsonscroll_to_bottom: 回到底部第 1564 行{count} 条新弹幕点击回到底部。这正是 320px 视口下长文案的来源——英文{count} new messages - tap to resume在 2 倍字号下的渲染宽度远超按钮可用宽度因此测试使用真实 zh/en JSON 而非桩文案来度量避免假阴性。渲染上按钮采用FilledButton.iconValueListenableBuilderint监听_pendingMessageCount计数为 0 时显示静态回到底部大于 0 时切换为累计数文案。i18n 经 core/utils/i18n.dart 封装 EasyLocalization 的tr(key, namedArgs)参数{count: $count}即注入占位符{count}。七、可复核证据与构建记录审计的每一条结论都附有可复核的本地证据以下路径按原审计记录给出原始目录local-artifacts/danmaku-resume-20260909/含 baseline.json、red/green 脚本、日志及源码哈希红测记录local-artifacts/build-records/20260908T210104138Z-danmaku-resume-red.json耗时 258.167 秒测试退出 1结束活跃重型进程 0绿测记录local-artifacts/build-records/20260908T211204803Z-danmaku-resume-green.json耗时 513.055 秒19/19 通过、analyze 无问题峰值 CPU 60.68%、Working Set 12,258,516,992 B结束活跃重型进程 0绿测实际输入 SHA-256生产文件256F8C769D2ABBA76B65583FF7AB6B1CA673D56E3350B0C69E2E47B3C10C3438新增测试99DDA149E8AFAF967304604A3AF19E698E01ED044790A5CA52C3EC8C53D8F9C0。提交前逐项一致、diff 检查通过生产文件lib/domains/live/presentation/playback/widgets/danmaku/danmaku_list_view.dart当前仓库实际路径含left: 12修复新测试test/danmaku_list_resume_test.dart本地候选验证文件本次审计的核心定向测试。八、剩余验收边界与回滚策略8.1 不把 Widget 视口外推到实机下一步计划将本修订纳入下一次累计候选并核验真实 Android 的中英文/大字号、横竖屏/短高度、小窗PiP以及 Windows 的窄窗口/滚轮表现——明确不把 Widget 测试的 640 高视口外推到所有高度和字体组合。快速滚动、关键词管理及 120 Hz 长期呈现按原矩阵继续历史实机证据见 列表累计数审计含斗鱼高消息量房间的暂停/恢复截图证据。8.2 宏观口径与回滚宏观上42 个未闭环项、10 组未注册参考平台、bee143e2的 38 组候选原生场景保持原口径这些范围重叠不相加。回滚策略为单独反向提交f35e605的生产布局改动以恢复基线——因为只动了布局约束没有配置或数据库迁移原候选及用户数据全部保持。小结本次审计的完整方法论值得复用先把故障精确归因到布局约束而非功能状态机再用真实本地化资源 生产 Widget 真实拖动在窄视口/大字号两个维度复现越界并量化左边界修复以left: 12三边约束 右对齐Align同时满足长文案不越界与短按钮不拉满最后用 19/19 定向测试锁定边界、保留相邻回归、明确实机验收边界与独立回滚路径。这一红测量化—局部修复—绿测锚定—边界声明的闭环正是 pure_live 在弹幕列表交互A4-02上持续收敛的工程范式。赞分享音视频直播移动开发【免费下载链接】pure_live纯粹直播:哔哩哔哩/虎牙/斗鱼/快手/抖音/网易cc/YY直播/Twitch直播/SOOP直播/M38自定义源应有尽有。项目地址https://gitcode.com/gh_mirrors/pur/pure_live点击查看免费下载相关推荐从 0 到 1 写出第一个 AI Agentawesome-agentic-ai-zh 手把手拆解 Agent Loop 与函数调用从 0 到 1 写出第一个 AI Agentawesome agentic ai zh 手把手拆解 Agent Loop 与函数调用 awesome agen音视频直播移动开发Pure Live Android 小窗弹幕设置无障碍语义修复与恢复默认行为审计Pure Live Android 小窗弹幕设置无障碍语义修复与恢复默认行为审计 本篇技术指南基于 Pure Live 仓库的 Android 小窗弹幕无障碍与音视频直播移动开发Pure Live 共用列表页布局审计提示区、状态页与分页栏的边界修复实录Pure Live 共用列表页布局审计提示区、状态页与分页栏的边界修复实录 本文围绕 pure_live 仓库中的共用列表页组件 BasePageView 与音视频直播移动开发上一篇告别配色烦恼用colors.css轻松掌握互补色与类似色搭配下一篇Claude-Code-Usage-Monitor的部署方案从Docker容器化到Web仪表板的完整实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表