已开启
fix: 修复开关动画中断后仍应用过期状态[update verson to 1.0.7-beta.1] #17
fix: 修复开关动画中断后仍应用过期状态[update verson to 1.0.7-beta.1] #17
已开启
yesses创建于 15 天前
yesses
yesses
15 天前

变更概述

本 PR 对鸿蒙化三方库 react-native-switch-pro 修复开关动画中断时的状态一致性问题,并更新版本号:

  • 修复开关动画被打断(finished === false)时仍应用过期目标状态的问题(增加 finished 守卫)
  • 移除切换完成后多余的 switchAnimation.setValue(±1) 回拨,动画值行为对齐上游 1.0.5
  • 版本号 1.0.6 -> 1.0.7-beta.1(package.json)

一、三方库源码修改点(重点)

1. 动画被打断时不再应用过期状态

根因:toggleSwitchToValue 中 animateSwitch 的完成回调不区分动画是否正常结束。动画被新的切换或手势打断(finished === false)时,回调仍执行 setState 更新内部 value 并触发用户 callback,把已被打断的过期目标状态应用到 UI 和外部状态,造成内外状态不一致。

修改前——回调不检查 finished,且切换完成后手动回拨动画值:

toggleSwitchToValue = (result, toValue, callback = () => null) => {
  const { switchAnimation } = this.state

  this.animateHandler(this.handlerSize)
  if (result) {
    this.animateSwitch(toValue, () => {
      this.setState({
        value: toValue,
        alignItems: toValue ? 'flex-end' : 'flex-start'
      }, () => {
        callback(toValue)
      })
      switchAnimation.setValue(toValue ? -1 : 1)
    })
  }
}

修改后——增加 finished 守卫,去掉多余 setValue:

toggleSwitchToValue = (result, toValue, callback = () => null) => {
  this.animateHandler(this.handlerSize)
  if (result) {
    this.animateSwitch(toValue, ({ finished }) => {
      if (!finished) return
      this.setState({
        value: toValue,
        alignItems: toValue ? 'flex-end' : 'flex-start'
      }, () => {
        callback(toValue)
      })
    })
  }
}
  • 动画被中断时直接返回,不 setState、不触发 callback,内部状态与 UI 保持一致
  • switchAnimation.setValue(toValue ? -1 : 1) 可去掉:切换完成后动画值停在 ±offset,render 插值配置了 extrapolate: 'clamp',视觉已位于新状态端点,无需手动回拨;行为对齐上游 1.0.5

二、文档修改

  • package.json:版本号 1.0.6 -> 1.0.7-beta.1

三、自测说明

  • 基础切换:点击后 200ms 平滑动画,无回闪(待人工验证)
  • 快速连续点击 / 动画中再次切换:最终状态与最后一次操作一致,内部状态不错位(待人工验证)
  • onSyncPress / onAsyncPress 成功与失败:回调参数为切换后的布尔值(待人工验证)
  • 外部修改 value:有 200ms 动画过渡,非瞬时跳变(待人工验证)

资料修改

  • 是否已在 README 和 package.json 修改了版本信息:是(package.json 版本号 1.0.6 -> 1.0.7-beta.1;README 无版本相关内容需更新)

Checklist

likedislike
合并受阻
openharmony_ci
openharmony_ci成员
15 天前 评论:

感谢提交 Pull Requests!
Thanks for submitting a pull request.

likedislike
openharmony_ciopenharmony_ci成员
15 天前 添加了label:dco检查成功
cpf-manager
cpf-manager15 天前进行代码检视1
lib/index.js
@@ -148,4 +147,4 @@
148147 alignItems: toValue ? 'flex-end' : 'flex-start'
149148 }, () => {
150149 callback(toValue)
151150 })
cpf-manager
cpf-manager15 天前评论:

【AI-Review】【严重】【基础代码问题】【代码逻辑错误】删除 setValue 导致下一次切换动画前半段被 clamp 冻结

● 问题:本次删除了 toggleSwitchToValue 回调末尾的 switchAnimation.setValue(toValue ? -1 : 1)(base 版本 lib/index.js:152)。但 animateSwitch(lib/index.js:155-166)结束时 switchAnimation 停留在 ±this.offset(默认 width-height+1=20),该值落在 render 中 interpolatedTranslateX 的 inputRange(lib/index.js:218 value ? [-this.offset, -1] : [1, this.offset],即 [-20,-1] 或 [1,20])之外。下一次 toggleSwitchToValue 被调用时(来自 _onPanResponderRelease→toggleSwitch→toggleSwitchToValue 的手势路径,或 componentWillReceiveProps→toggleSwitchToValue 的外部 prop 变更路径),animateSwitch 会从 ±this.offset 动画到 ∓this.offset,整段动画 40 个单位中只有 19 个单位落在 inputRange 内。由于 extrapolate: 'clamp' 的作用,前 21 个单位(52.5%,约 105ms)输出被钳制为边界值,圆点保持不动;后 19 个单位(47.5%,约 95ms)才真正位移。例如开关从 true→false 时,switchAnimation 从 20→-20,但前 105ms 圆点始终停在 circlePosition(true)=-1 处,后 95ms 才从 -1 移动到 -20,用户感知到"先静止 105ms 再快速移动 95ms"的卡顿。

● 影响:严重。每次完成一次切换后,紧接着的下一次切换动画都会出现前半段冻结的视觉卡顿,与 200ms 线性动画的预期不符,用户会明显感知到开关响应延迟。base 版本依赖被删除的 setValue 将 switchAnimation 重置到 -1/1(落在新 inputRange 的边界内),下一次动画从 inputRange 内的值起步,全程线性可见,不存在该卡顿。本次修改相当于用一个更严重的动画卡顿换取了对中断场景的修复。

● 建议:保留对中断动画的 if (!finished) return 处理,但不要简单删除 setValue。可参考 0.77 分支(br_rnoh0.77,commit 5e95759)executeToggleToValue(lib/index.js:145-166)的实现思路:先 switchAnimation.stopAnimation(),再 setState,然后用 setValue(toValue ? -this.offset : this.offset) 将动画起点显式设置到新 inputRange 的边界内,最后 Animated.timing 到目标值。这样既能避免 base 版本 setValue 与 setState 时序错位导致的"跳变",又能让下一次切换的动画起点落在 inputRange 内。或在本次最小改动范围内,将 switchAnimation.setValue(toValue ? -1 : 1) 保留并移到 setState 调用之前执行,以消除时序错位而非删除该重置。

likedislike
yessesyesses
15 天前 强制推送  1 个提交:7b890f83-fix: external state change causing the switch animation to disappear; onAsyncPress toggles UI before rolling back on failure
yessesyesses
15 天前 修改标题为 “fix: 修复开关动画中断后仍应用过期状态[update verson to 1.0.7-beta.1]”,原标题为“fix: 修复开关动画中断后仍应用过期状态,补齐与 0.77 线(PR #16)一致的最终修复”
yessesyesses
15 天前 修改了pull request 的描述
openharmony_ci
openharmony_ci成员
15 天前 评论:

感谢提交 Pull Requests!
Thanks for submitting a pull request.

likedislike