applyPhysicsToUserOffset method
将物理效果应用到用户拖动偏移上
该方法用于控制用户拖动时的滚动行为,特别是在超出边界时的效果
参数:
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);
}