- 看了一下源码,研究了一下ScrollPhysics,记录下学习的知识
- 首先我们自定一个ScrollPhysics
//边界条件
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
// TODO: implement applyBoundaryConditions
print('applyBoundaryConditions-value: ' + value.toString());
print('applyBoundaryConditions-pixels: ' + position.pixels.toString());
print('applyBoundaryConditions-minScrollExtent: ' + position.minScrollExtent.toString());
// assert(() {
// if (value == position.pixels) {
// throw FlutterError.fromParts(<DiagnosticsNode>[
// ErrorSummary('$runtimeType.applyBoundaryConditions() was called redundantly.'),
// ErrorDescription(
// 'The proposed new position, $value, is exactly equal to the current position of the '
// 'given ${position.runtimeType}, ${position.pixels}.\n'
// 'The applyBoundaryConditions method should only be called when the value is '
// 'going to actually change the pixels, otherwise it is redundant.'
// ),
// DiagnosticsProperty<ScrollPhysics>('The physics object in question was', this, style: DiagnosticsTreeStyle.errorProperty),
// DiagnosticsProperty<ScrollMetrics>('The position object in question was', position, style: DiagnosticsTreeStyle.errorProperty)
// ]);
// }
// return true;
// }());
// if (value < position.pixels && position.pixels <= position.minScrollExtent) // underscroll
// return value - position.pixels;
// if (position.maxScrollExtent <= position.pixels && position.pixels < value) // overscroll
// return value - position.pixels;
// if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) // hit top edge
// return value - position.minScrollExtent;
// if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) // hit bottom edge
// return value - position.maxScrollExtent;
return 0.0;
}
通过上面的代码我们总结一组数据:
手指向上滑动
flutter: applyBoundaryConditions-value: 1.1666666666666667
flutter: applyBoundaryConditions-pixels: 0.0
flutter: applyBoundaryConditions-value: 3.833323160807292
flutter: applyBoundaryConditions-pixels: 1.1666666666666667
flutter: applyBoundaryConditions-value: 7.4999949137369795
flutter: applyBoundaryConditions-pixels: 3.833323160807292
flutter: applyBoundaryConditions-value: 9.49999491373698
flutter: applyBoundaryConditions-pixels: 7.4999949137369795
flutter: applyBoundaryConditions-value: 10.833323160807293
flutter: applyBoundaryConditions-pixels: 9.49999491373698
手指向下滑动
flutter: applyBoundaryConditions-value: -1.1666666666666667
flutter: applyBoundaryConditions-pixels: 0.0
flutter: applyBoundaryConditions-value: -14.083282571507818
flutter: applyBoundaryConditions-pixels: -1.1666666666666667
flutter: applyBoundaryConditions-value: -26.803620940222785
flutter: applyBoundaryConditions-pixels: -14.083282571507818
flutter: applyBoundaryConditions-value: -32.96262340368834
flutter: applyBoundaryConditions-pixels: -26.803620940222785
flutter: applyBoundaryConditions-value: -43.17358141473012
flutter: applyBoundaryConditions-pixels: -32.96262340368834
flutter: applyBoundaryConditions-value: -49.855403819187806
value: 滑动距离 往下(手指向着屏幕下方移动)值小于0,往上(手指向着屏幕上方移动)值大于于0
pixels: offset.y类似,这个值和value有一定关系,看到上面没次打印的值value的值最后都给了pixels, 所以这两个应该是不可能==的
测试发现返回0的时候,滑动超出了内容,会反弹,应该是触发了Simulation createBallisticSimulation动画,可以看源码里面有这个方法
打开这段代码
if (value < position.pixels && position.pixels <= position.minScrollExtent) // 往下滑
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value) // overscroll
return value - position.pixels;
if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) // hit top edge
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) // hit bottom edge
return value - position.maxScrollExtent;
上面这段代码完成了什么功能,达到了不能回弹的效果呢?
来打印数据看
@override
double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
// TODO: implement applyPhysicsToUserOffset
print('applyBoundaryConditions-offset: ' + offset.toString());
return super.applyPhysicsToUserOffset(position, offset);
}
@override
double applyBoundaryConditions(ScrollMetrics position, double value) {
// TODO: implement applyBoundaryConditions
print('applyBoundaryConditions-value: ' + value.toString());
print('applyBoundaryConditions-pixels: ' + position.pixels.toString());
print('applyBoundaryConditions-value-pixels: ' + (value - position.pixels).toString());
print('--------------------------------------------------');
if (value < position.pixels && position.pixels <= position.minScrollExtent) // underscroll
return value - position.pixels;
if (position.maxScrollExtent <= position.pixels && position.pixels < value) // overscroll
return value - position.pixels;
if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) // hit top edge
return value - position.minScrollExtent;
if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) // hit bottom edge
return value - position.maxScrollExtent;
return 0.0;
}
flutter: applyBoundaryConditions-offset: 1.1666666666666667
flutter: applyBoundaryConditions-value: 0.8333333333333333
flutter: applyBoundaryConditions-pixels: 2.0
flutter: applyBoundaryConditions-value-pixels: -1.1666666666666667
flutter: --------------------------------------------------
flutter: applyBoundaryConditions-offset: 12.666656494140625
flutter: applyBoundaryConditions-value: -11.833323160807291
flutter: applyBoundaryConditions-pixels: 0.8333333333333333
flutter: applyBoundaryConditions-value-pixels: -12.666656494140625
flutter: --------------------------------------------------
flutter: applyBoundaryConditions-offset: -1.1666666666666667
flutter: applyBoundaryConditions-value: 1.1666666666666667
flutter: applyBoundaryConditions-pixels: 0.0
flutter: applyBoundaryConditions-value-pixels: 1.1666666666666667
flutter: --------------------------------------------------
flutter: applyBoundaryConditions-offset: -3.0
flutter: applyBoundaryConditions-value: 4.166666666666667
flutter: applyBoundaryConditions-pixels: 1.1666666666666667
flutter: applyBoundaryConditions-value-pixels: 3.0
flutter: --------------------------------------------------
flutter: applyBoundaryConditions-offset: -6.666656494140625
flutter: applyBoundaryConditions-value: 10.833323160807293
flutter: applyBoundaryConditions-pixels: 4.166666666666667
flutter: applyBoundaryConditions-value-pixels: 6.666656494140626
flutter: --------------------------------------------------
applyPhysicsToUserOffset这个方法,返回的数据就是告诉widget移动的相对位置,这个方法应该还需要和applyBoundaryConditions边界条件来配合使用,从上面打印的数据来看,value-pixels + offset = 0 的时候无法滚动, 系统应该是怎么判断呢的, 我猜测 如果边界条件返回0那么越过边界后就会创建Simulation回弹效果, 如果边界条件返回的值和offset的值之和==0那么拉动的距离和边界条件的值低消了, 就不能越过边界。
applyBoundaryConditions中返回 非0值的时候,可以越过边界, 但是没有了Simulation回弹效果。
网友评论