applyPhysicsToUserOffset method

  1. @override
double applyPhysicsToUserOffset(
  1. ScrollMetrics position,
  2. double offset
)
override

将物理效果应用到用户拖动偏移上

该方法用于控制用户拖动时的滚动行为,特别是在超出边界时的效果

参数:

  • position:滚动位置信息
  • offset:用户拖动的偏移量
  • 返回值:应用物理效果后的偏移量

Implementation

@override

/// 将物理效果应用到用户拖动偏移上
///
/// 该方法用于控制用户拖动时的滚动行为,特别是在超出边界时的效果
///
/// 参数:
/// - [position]:滚动位置信息
/// - [offset]:用户拖动的偏移量
/// - 返回值:应用物理效果后的偏移量
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
  // 延迟初始化视口渲染对象
  viewportRender ??= findViewport(controller!.position?.context.storageContext);

  // 检查是否启用了下拉刷新或上拉加载
  final bool isPullDownEnabled = viewportRender?.firstChild is RenderSliverRefresh;
  final bool isPullUpEnabled = viewportRender?.lastChild is RenderSliverLoading;

  // 如果向上滚动但未启用下拉刷新,或向下滚动但未启用上拉加载,则使用父级物理效果
  if ((offset > 0.0 && !isPullDownEnabled) || (offset < 0 && !isPullUpEnabled)) {
    return parent!.applyPhysicsToUserOffset(position, offset);
  }
  // 处理超出范围或二级刷新状态的情况
  if (position.outOfRange) {
    // 计算超出起始位置的距离
    final double overscrollPastStart = math.max(position.minScrollExtent - position.pixels, 0.0);
    // 计算超出结束位置的距离
    final double overscrollPastEnd = math.max(position.pixels - position.maxScrollExtent, 0.0);
    // 取两者中的最大值
    final double overscrollPast = math.max(overscrollPastStart, overscrollPastEnd);

    // 判断是否需要应用缓动效果
    final bool easing = (overscrollPastStart > 0.0 && offset < 0.0) || (overscrollPastEnd > 0.0 && offset > 0.0);

    // 计算摩擦系数
    final double friction = easing
        ? frictionFactor((overscrollPast - offset.abs()) / position.viewportDimension)
        : frictionFactor(overscrollPast / position.viewportDimension);

    // 计算方向和最终偏移量
    final double direction = offset.sign;
    return direction * _applyFriction(overscrollPast, offset.abs(), friction) * (dragSpeedRatio ?? 1.0);
  }

  // 默认情况下使用父级物理效果
  return super.applyPhysicsToUserOffset(position, offset);
}