0

How can I customize the physics property of PageView to have for example a ClampingScrollPhysics for the first page (edge overflow) and a BouncingScrollPhysics for the last page?

(My use case is to load pages on demand when scrolling the last page.)

Patrick
  • 3,578
  • 5
  • 31
  • 53
  • most likely you need a custom class extending [PageScrollPhysics](https://api.flutter.dev/flutter/widgets/PageScrollPhysics-class.html) – pskink Aug 30 '23 at 15:51
  • Yes but how? This is the question. – Patrick Aug 30 '23 at 17:17
  • the similar way `PageScrollPhysics` extends `ScrollPhysics`: https://github.com/flutter/flutter/blob/ff5b5b5fa6/packages/flutter/lib/src/widgets/page_view.dart#L532 - the most important part is to override `applyTo` method, otherwise no other custom overriden method will be called at all – pskink Aug 30 '23 at 18:06

1 Answers1

1

I tested this very little, so make sure you test it properly.

Code (see comments):

class MyScrollPhysics extends ScrollPhysics {
  const MyScrollPhysics({super.parent});

  @override
  MyScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return MyScrollPhysics(parent: buildParent(ancestor));
  }

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) {
    /// This is the important part, where we can allow overscrolling of the
    /// list, but not underscrolling.

    if (value < position.pixels &&
        position.pixels <= position.minScrollExtent) {
      // Underscroll.
      return value - position.pixels;
    }

    if (value < position.minScrollExtent &&
        position.minScrollExtent < position.pixels) {
      // Hit top edge.
      return value - position.minScrollExtent;
    }

    /// If it's not a left or top boundary, then we allow overscrolling.
    return .0;
  }

  @override
  Simulation? createBallisticSimulation(
    ScrollMetrics position,
    double velocity,
  ) {
    final tolerance = toleranceFor(position);

    /// The simulation will be the typical bouncing scroll simulation.
    if (velocity.abs() >= tolerance.velocity || position.outOfRange) {
      return BouncingScrollSimulation(
        spring: spring,
        position: position.pixels,
        velocity: velocity,
        leadingExtent: position.minScrollExtent,
        trailingExtent: position.maxScrollExtent,
        tolerance: tolerance,
        constantDeceleration: .0,
      );
    }

    return null;
  }
}

Usage:

PageView(
  physics: const MyScrollPhysics(),
  children: [
    Container(color: Colors.red),
    Container(color: Colors.green),
    Container(color: Colors.blue),
  ],
);
offworldwelcome
  • 1,314
  • 5
  • 11
  • Thanks, it works! But for a better rendering, I also overrode applyPhysicsToUserOffset. I also used a local BouncingScrollPhysics object to avoid copy/paste. – Patrick Aug 30 '23 at 19:17