flutter applyBoundaryConditions 方法的理解

199 阅读1分钟
 double applyBoundaryConditions(ScrollMetrics position, double value) {

参数 第一个参数就是滑动信息 第二个参数 就是新的即将设置的偏移量。 比如poistion.pixels = 100,用户向上滑动 10,那么value 就是 100.

applyBoundaryConditions 的使用逻辑理解

  double setPixels(double newPixels) {
    if (newPixels != pixels) {
      final double overscroll = applyBoundaryConditions(newPixels);
      final double oldPixels = pixels;
      _pixels = newPixels - overscroll;
      if (_pixels != oldPixels) {
        notifyListeners();
        didUpdateScrollPositionBy(pixels - oldPixels);
      }
      if (overscroll.abs() > precisionErrorTolerance) {
        didOverscrollBy(overscroll);
        return overscroll;
      }
    }
    return 0.0;
  }

newPixels 的值是当前处理完用户手指偏移量后的最终偏移量。

pixels - physics.applyPhysicsToUserOffset(this, delta)

overscroll 默认返回的是0.所以_pixels != oldPixels一般是成立的。就会调用 didUpdateScrollPositionBy来进行真正的滑动。overscroll.abs() > precisionErrorTolerance一般是不成立的。所以不会触发越界逻辑。

再以 ClampingScrollPhysics.applyPhysicsToUserOffset 实现为例

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) {
     //1 下拉 并且越界
    if (value < position.pixels && position.pixels <= position.minScrollExtent) {
      // Underscroll.
      return value - position.pixels;
    }
    //2 上拉 并且越界
    if (position.maxScrollExtent <= position.pixels && position.pixels < value) {
      // Overscroll.
      return value - position.pixels;
    }
    //3 即将滑动小于最小值 但是 还没滑动小于最小值
    if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) {
      // Hit top edge.
      return value - position.minScrollExtent;
    }
    //4 还没滑动到最大值 并且即将超过最大值
    if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) {
      // Hit bottom edge.
      return value - position.maxScrollExtent;
    }
    return 0.0;
  } 

简单来说 ClampingScrollPhysics.applyPhysicsToUserOffset 返回的是超过边界的数值。 所以越界之后 overscroll不为0.

_pixels = newPixels - overscroll 计算的结果就是列表滑动到边界需要移动的距离。

第一种情况

_pixels = newPixels - (value - position.pixels)

value = newPixels 

所以 _pixels = position.pixels

oldPixels = position.pixels 

所以 _pixels != oldPixels 不成立。所以不会移动。

第二种情况

_pixels = newPixels - (value - position.pixels)

value = newPixels 

所以 _pixels = position.pixels

oldPixels = position.pixels 

所以 _pixels != oldPixels 不成立。所以不会移动。

第三种情况

_pixels = newPixels - (value - position.minScrollExtent)

value = newPixels 

所以 _pixels = position.minScrollExtent

oldPixels = position.pixels 

所以 _pixels != oldPixels 成立,移动距离为pixels - oldPixels = position.minScrollExtent - position.pixels 

第四种情况

_pixels = newPixels - (value - position.maxScrollExtent)

value = newPixels 

所以 _pixels = position.maxScrollExtent

oldPixels = position.pixels 

所以 _pixels != oldPixels 成立,移动距离为pixels - oldPixels = position.maxScrollExtent - position.pixels