animationSlide method

dynamic animationSlide(
  1. double left,
  2. double toPositionX,
  3. int time,
  4. VoidCallback? completed,
)

Implementation

animationSlide(double left, double toPositionX, int time, VoidCallback? completed) {
  // 停止并重用已有 controller,设置时长
  if (_slideController.isAnimating) _slideController.stop();
  if (fx == toPositionX) {
    // 位置相同则直接回调完成
    try {
      if (completed != null) completed();
    } catch (_) {}
    return;
  }
  _slideController.duration = Duration(milliseconds: time);

  // 关键保护:如果时长为 0 或负数,不要调用 .forward(),因为在 Flutter 内部这会触发
  // 'simulationDuration > Duration.zero' 的断言。改为立即把位置设置为目标值,并调用完成回调。
  // 使用 null 合并以保证在空安全下不会对 null 调用比较运算符。
  if ((_slideController.duration ?? Duration.zero) <= Duration.zero) {
    // 立即应用最终位置并通知(同步完成)
    fx = toPositionX * 1.0;
    handlerSaveCacheDataAndNotify(fx, fy);
    try {
      if (completed != null) completed();
    } catch (_) {}
    return;
  }

  // 移除上一次 listener,避免重复添加
  if (_slideListener != null) {
    try {
      _slideAnimation.removeListener(_slideListener!);
    } catch (_) {}
    _slideListener = null;
  }

  // tween 从当前 x 到目标位置,确保能从任意起点动画到目标
  _slideAnimation = Tween(begin: fx, end: toPositionX * 1.0).animate(_slideController);
  // 回弹动画监听:更新 fx 并保存/通知
  _slideListener = () {
    fx = _slideAnimation.value.toDouble();
    handlerSaveCacheDataAndNotify(fx, fy);
  };
  _slideAnimation.addListener(_slideListener!);

  // 状态监听:动画完成后移除 listener 并回调
  void _statusHandler(AnimationStatus status) {
    if (status == AnimationStatus.completed) {
      // remove listener after complete to avoid leak
      if (_slideListener != null) {
        try {
          _slideAnimation.removeListener(_slideListener!);
        } catch (_) {}
        _slideListener = null;
      }
      // 调用外部回调(如果有)
      try {
        if (completed != null) completed();
      } catch (_) {}
      _slideController.removeStatusListener(_statusHandler);
    }
  }

  _slideController.addStatusListener(_statusHandler);
  _slideController.forward(from: 0.0);
}