0

and today when I am developing my app, I just find out that I need a feature that can only allow user to scroll to the right page, but not the left page, and the PageController does not provide any functionality that can allow me to implement that, so that's the reason why I am here!

I also visited this link:

StackOverflow: Custom ScrollPhysics, but it does not contain any explanation, you know it's painful to use other people's code without knowing what it is doing, right? So please help me!!! ^_^

Ryan Wang
  • 418
  • 7
  • 23

1 Answers1

2

You can create your own ScrollPhysics to lock the scroll to a direction, or you can use the horizontal_blocked_scroll_physics lib to help you.

Here is an example of a CustomScrollPhysic that enable only right scrolling

class CustomScrollPhysics extends ScrollPhysics {
  CustomScrollPhysics({ScrollPhysics parent}) : super(parent: parent);

  bool isGoingLeft = false;

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

  @override
  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    isGoingLeft = offset.sign < 0;
    return offset;
  }

  @override
  double applyBoundaryConditions(ScrollMetrics position, double value) {
    assert(() {
      if (value == position.pixels) {
        throw FlutterError(
          '$runtimeType.applyBoundaryConditions() was called redundantly.\n'
          '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.\n'
          'The physics object in question was:\n'
          '  $this\n'
          'The position object in question was:\n'
          '  $position\n');
      }
      return true;
    }());
    if (value < position.pixels && position.pixels <= position.minScrollExtent)
      return value - position.pixels;
    if (position.maxScrollExtent <= position.pixels && position.pixels < value)
      return value - position.pixels;
    if (value < position.minScrollExtent &&
        position.minScrollExtent < position.pixels)

      return value - position.minScrollExtent;

    if (position.pixels < position.maxScrollExtent &&
        position.maxScrollExtent < value)
      return value - position.maxScrollExtent;

    if (!isGoingLeft) {
      return value - position.pixels;
    }
    return 0.0;
  }
}

You can use as the example below, CustomScrollPhysics as value to physics parameter.

PageView.builder(
  physics: CustomScrollPhysics(),
);

Some references that could explain better how ScrollPhysics works

  • Very appreciate your response, but do you have a way to solve my case without adding a new package, because my app is already 200 mb large in size, and afraid to add a new package... @_@ – Ryan Wang Apr 28 '21 at 04:14
  • I added a new code example! I think it could help you – Guilherme Gabanelli Apr 28 '21 at 14:44
  • 1
    Yes, thank you for the patient, but an explanation for it will be nice, or do you know any tutorials about this, so that I can dive deep into the codes of how it works? :) – Ryan Wang Apr 29 '21 at 01:51
  • You're welcome! I've added some references that could explain better the behavior of the `ScrollPhysics`. The main function of this code is `applyBoundaryConditions`, it validates if the user can scroll or not, using the position and the scroll value as parameter to evaluate. – Guilherme Gabanelli Apr 29 '21 at 04:28