Files
FruitServer/docs/plans/2026-10-21-K87.1-pull-refresh-freeze.md

2.3 KiB
Raw Permalink Blame History

K87.1 下拉刷新冻结位移实施计划

目标

修复刷新 pending 期间仍从松手距离回收到 56px 的视觉回弹。达到阈值后冻结当前下拉距离 D,刷新完成前 offset 不变化,完成后才用 200ms easeOut 回到 0。

根因

  • K87 已将系统 physics 改为 Clamping,避免原生 overscroll 回弹叠加。
  • 但 _refresh 仍先执行 _animateOffsetTo(_holdDistance),会把松手时的 D(例如 96)回收到 56。
  • 用户感知为“页面已经弹回去”,实际是组件自身在刷新开始时主动缩短 offset。

范围

  • ReelShort lib/core/widgets/app_pull_to_refresh.dart
  • ReelShort test/core/app_pull_to_refresh_test.dart
  • FruitServer docs/plans/PROGRESS.md

实现计划

  1. 保留 AlwaysScrollableScrollPhysics(parent: ClampingScrollPhysics()),系统不移动 overscroll 内容。
  2. 删除 _holdDistance 与刷新前的 56px 过渡动画。
  3. 达到阈值松手后立即进入 refreshing,AnimationController 保持当前 D;刷新期间滚动通知和手势均忽略。
  4. onRefresh 完成后再从 D 执行 200ms easeOut 回 0,指示器随 offset 淡出。
  5. 未达阈值松手时新增 _retracting 状态,执行 200ms easeOut 回到 0,不触发 onRefresh。

测试计划

  • 达阈值测试:记录松手 offset D,挂起 300ms 后仍等于 D;刷新中重复下拉不改变 D、不增加调用。
  • complete 后断言 offset 回 0、指示器消失。
  • 未达阈值测试:松手后立即开始回弹,100ms 时 offset 介于 0 与 D 之间,最终回 0 且 onRefresh 未调用。
  • 断言 AppPullToRefresh.physics.parent 为 ClampingScrollPhysics。

风险与处理

  • 保持 D 时下拉越高,内容下移越明显,但这是用户松手时的真实位置,刷新完成后才回收。
  • 未达阈值回弹期间通过 _retracting 忽略新滚动通知,避免动画目标被手势覆盖。
  • 不逐个页面改动,所有使用共享 physics 与组件的页面自动生效。

Git

  • ReelShort 从 develop 创建 fix/pull-refresh-freeze。
  • 提交:fix(ui): 下拉刷新刷新期间冻结下拉位移。
  • 作者:Zhou Weidong <502333560@qq.com>。
  • --no-ff 合回 develop 并 push,不使用 force push,不执行 git add -A。
  • FruitServer 追加 PROGRESS 留痕;不安装真机,完成后等待用户验收。